Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate criteria join table issue

I have 3 entities as you can see below. I want to write a query that fetches products. In this query the parameter is a list of 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:

 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);

    }
like image 319
Emil Avatar asked Apr 27 '17 17:04

Emil


People also ask

How to use join in Criteria in Hibernate?

Criteria in Hibernate can be used for join queries by joining multiple tables, useful methods for Hibernate criteria join are createAlias(), setFetchMode() and setProjection() Criteria in Hibernate API can be used for fetching results with conditions, useful methods are add() where we can add Restrictions.

How to write join query in Hibernate?

We can apply the Joins in Hibernate by using the HQL query or native SQL query. To make a join between the two tables, the two tables must be in a logical relationship. We can achieve the relationship between two tables by applying the parent table's primary key as a child table's foreign key.

Is Hibernate criteria deprecated?

Since Hibernate 5.2, the Hibernate Criteria API is deprecated, and new development is focused on the JPA Criteria API. We'll explore how to use Hibernate and JPA to build Criteria Queries.

What is join table in Hibernate?

When a join table is used in mapping a relationship with an embeddable class on the owning side of the relationship, the containing entity rather than the embeddable class is considered the owner of the relationship. If the JoinTable annotation is missing, the default values of the annotation elements apply.


2 Answers

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.

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));
}
like image 112
mindas Avatar answered Sep 27 '22 17:09

mindas


an even easier solution would be to use a 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:

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.

For the solution with EntityManager i am assuming you already were able to instantiate one.

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()

like image 37
XtremeBaumer Avatar answered Sep 27 '22 18:09

XtremeBaumer