我有一张桌子 产品(ProductId,Name)和 ProductPrices(ProductId,Market,Price)
ProductPrices有一个compositeKey(ProductId,Market)。对于给定的市场,产品在该市场中的价格为0..1。
市场在运行时是已知的,并且可以根据请求进行更改。 在第一次尝试对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(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");
}
};
}
然而,这只会导致(我尝试写作&#34;市场&#34;,&#34;市场&#34;,......)
org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'generatedAlias1.market' [select generatedAlias0 from ...backend.entities.Product as generatedAlias0 where generatedAlias1.market in (:param0)]
这一次,我在产品实体中写道
@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?谢谢!的
答案 0 :(得分:1)
第二种方法实际上是正确的。尝试改变你的实体和creteria查询。
产品表:
@Entity
@Table(...)
public class Product {
@Id
private int ProductId;
private String name;
@OneToMany(mappedBy = "products")
private List<ProductPrices> ProductPrices;
}
ProductPrices表:
@Entity
@Table(...)
public class ProductPrices {
@Id
private int ProductPriceId;
private String market;
private double price;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "product_id") //foreign key reference
private Product products
}
产品服务:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Product> qry = cb.createQuery(Product.class);
Root<Product> root = qry.from(Product.class);
Join<Product, ProductPrices> price = root.join("ProductPrices");
List<Predicate> conditions = new ArrayList<>();
conditions.add(cb.equal(price.get("products"), "Berlin"));
TypedQuery<Product> typedQuery = em.createQuery(qry
.select(root)
.where(conditions.toArray(new Predicate[] {}))
.orderBy(cb.asc(root.get("Berlin")))
.distinct(true)
);
return typedQuery;