【发布时间】:2015-08-12 10:21:49
【问题描述】:
我有一张桌子 产品 ( ProductId, Name ) 和 ProductPrices(ProductId、市场、价格)
ProductPrices 有一个复合键(ProductId,Market)。对于给定的市场,产品在该市场中的价格为 0..1。
第一种方法@Formula
市场在运行时是已知的,并且可以根据请求进行更改。 在第一次尝试对 ProductEntity 建模时,我使用了 @Formula 注释,如下所示:
@Entity
@Table(...)
public class Product {
@Id
private int ProductId;
private String name;
@Formula("(SELECT TOP 1 Price FROM ProductPrices p WHERE p.ProductId = ProductId AND p.Market='Berlin')")
private double price;
}
但显然,市场随后是硬编译的,因为注释需要是静态的最终字符串。 [所以没有 @Formula("..." + getCurMarket() ) ]。
第二种方法,@OneToMany
>为价格获取一个单独的实体类,并在产品实体中将它们引用为:
@OneToMany(mappedBy = "product")
private List<Price> price;
在getPrice() 中,我总是可以返回第一个条目(永远不会有更多...),如果列表为空,则什么都不返回。
然后我想创建一个谓词/规范以在 ProductService 中使用。示例:
public static Specification<Product> marketEquals(final String market) {
return new Specification<Product>() {
@Override
public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
CriteriaQuery<String> q = cb.createQuery(String.class);
Root<Price> price = q.from(Price.class);
return price.get("Market").in("Berlin");
}
};
}
但是,这只会导致(我尝试写“市场”、“市场”……)
org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'generatedAlias1.market' [select generatedAlias0 from ...backend.entities.Product as generatedAlias0 where generatedAlias1.market in (:param0)]
第三种方法,Hibernate/JPA 过滤器
这次我写在产品实体里
@OneToMany(mappedBy = "product")
@Filters( {
@Filter(name="marketFilter", condition="Market = :market")
} )
private List<Price> price;
再次,我想在 ProductService 中填写此过滤器,但我无法掌握 CurrentSession。我尝试了Spring-way,添加了@Autowired private SessionFactory sessionFactory;并通过配置
Filter filter = sessionFactory.getCurrentSession().enableFilter("marketFilter");
filter.setParameter("market", "Berlin" );
但我无法掌握正确的上下文,如org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory
谁能建议如何将数据库模式建模为实体,或者可以指出方法 2 和 3 的可行解决方案?谢谢!
【问题讨论】:
标签: java spring hibernate jpa spring-boot