[英]Hibernate criteria join table issue
I have 3 entities as you can see below. 我有3个实体,如下所示。 I want to write a query that fetches products. 我想写一个提取产品的查询。 In this query the parameter is a list of optionValues id. 在此查询中,参数是optionValues id的列表。
now my question is how to join these entities? 现在我的问题是如何加入这些实体?
Product: 产品:
public class Product{
//other col
@OneToMany(mappedBy = "product")
private Set<Attribute> attributeSet = new HashSet<>();
}
Attribute: 属性:
public class Attribute{
@OneToOne
@JoinColumn(name = "OPTION_VALUE_ID")
private OptionValue optionValue;
@ManyToOne
@JoinColumn(name="PRODUCT_ID",referencedColumnName="id")
private Product product;
}
optionValue: optionValue:
public class OptionValue{
@Column(name = "id")
private Long id;
@Column(name = "value",updatable = true)
private String value;
}
I wrote a query but I think my code is not a good solution. 我写了一个查询,但我认为我的代码不是一个好的解决方案。
Criteria aCriteria = null;
if (!optionValueList.isEmpty()) {
aCriteria = currentSession().createCriteria(Attribute.class, "attribute");
aCriteria.createAlias("attribute.optionValue", "optionValue");
aCriteria.add(Restrictions.in("optionValue.id", optionValueList));
attributes = aCriteria.list();
}
PagingData<Product> pagingData = new PagingData<>();
Criteria criteria = currentSession().createCriteria(Product.class, "product");
if (!attributes.isEmpty()) {
for (Attribute attribute:attributes){
longList.add(attribute.getId());
}
criteria.createAlias("product.attributeSet", "attribute");
criteria.add(Restrictions.in("attribute.id", longList));
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
}
The general idea is to start with creating criteria of objects you want to return, and travel further by adding criteria which is joined. 一般的想法是从创建要返回的对象的标准开始,并通过添加已连接的条件进一步传播。 So I start with Parent
class, add qualifiers and end up with most nested element, OptionValue
. 所以我从Parent
类开始,添加限定符并最终使用大多数嵌套元素OptionValue
。
Code below is untested, but you should get the idea: 下面的代码未经测试,但你应该明白:
Criteria criteria = currentSession()
.createCriteria(Product.class)
.createCriteria("attributeSet", "join_between_product_and_attribute");
if (!attributes.isEmpty()) {
Set<String> attributeIds = new HashSet<>();
for (Attribute attribute : attributeList) {
attributeIds.add(attribute.getId());
}
criteria.add(Restrictions.in("id", attributeIds));
}
criteria = criteria.createCriteria("optionValue", "join_between_attribute_optionvalue");
if (!optionValueList.isEmpty()) {
criteria.add(Restrictions.in("id", optionValueList));
}
an even easier solution would be to use a CriteriaQuery
. 更简单的解决方案是使用CriteriaQuery
。 i did not test the following code, but i think it should work correctly. 我没有测试以下代码,但我认为它应该正常工作。 it requires hibernate 5, but also works with some modifications in hibernate 4: 它需要hibernate 5,但也可以在hibernate 4中进行一些修改:
CriteriaBuilder cb = sessionFactory.getCriteriaBuilder();
CriteriaQuery<Product> query = cb.createQuery(Product.class);
Root<Product> r = query.from(Product.class);
In<Object> in = cb.in(r.join("attributeSet ").join("optionValue").get("id"));
for(Object optionValue : optionValueList){
in.value(optionValue);
}
query.select(r).where(in);
return sessionFactory.getCurrentSession().createQuery(query).getResultList();
i am assuming, that you can access the optionValueList
since you posted it in your question. 我假设,您可以访问optionValueList
因为您已将其发布在您的问题中。
For the solution with EntityManager
i am assuming you already were able to instantiate one. 对于使用EntityManager
的解决方案,我假设您已经能够实例化一个。
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Product> query = cb.createQuery(Product.class);
Root<Product> r = query.from(Product.class);
In<Object> in = cb.in(r.join("attributeSet ").join("optionValue").get("id"));
for(Object optionValue : optionValueList){
in.value(optionValue);
}
query.select(r).where(in);
return entityManager.createQuery(query).getResultList();
if you have an EntityManagerFactory
, replace the first entityManager
with it and the second one with entityManagerFactory.createEntityManager()
如果你有一个EntityManagerFactory
,用它替换第一个entityManager
,用entityManagerFactory.createEntityManager()
替换第二个
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.