0

I have the following setup

@Entity
@Table(name = "Product")
public class Product implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    private String name;

    @OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
    private final List<Item> itemlist = new ArrayList<Item>();

    //some other attributes, getter/setter
}

@Entity
@Table(name = "Item")
public class Item implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    private Date startDate;

    //some other attributes, getter/setter
}

The connection beween these classes is only unidirectional. If bidirectional connection is better (e.g. in terms of performance)?

How can i query all Items which were launched after a date (startDate) and to a specific product are assigned?

I try to implementing this with criteria api:

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Item> criteriaQuery = criteriaBuilder.createQuery(Item.class);
criteriaQuery = criteriaQuery.distinct(true);

Metamodel m = em.getMetamodel();
EntityType<Product> Product_ = m.entity(Product.class);
Root<Product> root = criteriaQuery.from(Product_);
Join join = root.join("itemlist");


Predicate condition = criteriaBuilder.equal(join.get("product"), selectedProduct);
criteriaQuery.where(condition);

criteriaQuery.select(join);

TypedQuery<Item> tq = em.createQuery(criteriaQuery);
System.out.println("result " + tq.getResultList());

I got the exception:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.test.Product.itemlist, no session or session was closed

Is there a problem with my Query or with the lazy itemlist?

Stefan
  • 63
  • 1
  • 2
  • 8

1 Answers1

0

This is probably stale but I had the code right at hand. This is how I solve this:

    CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
    CriteriaQuery<Product> criteriaQuery = criteriaBuilder.createQuery(Product.class);
    Root<Product> queryRoot = criteriaQuery.from(Product.class);

    Predicate idPredicate = criteriaBuilder.equal(queryRoot.get(Product_.id), id);
    criteriaQuery.where(idPredicate);

    TypedQuery<Product> typedQuery = em.createQuery(criteriaQuery);

    Product theProduct = typedQuery.getSingleResult();

    //this triggers the lazy relationship
    theProduct.getItemsList();

HTH!!!!

Federico

fedevela
  • 41
  • 1
  • 6
  • Do that in any production code and your performance will go down the drain. You end up with multiple queries. So, your solution works. It is a terrible solution. You would do better writing your own JPQL, using the Criteria API or Entity Graph. – harogaston Jul 07 '17 at 20:18