Reputation: 89
Imagine this relationshipt where a stock has many to many with category.
Stock
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "stock_category" , joinColumns = {
@JoinColumn(name = "STOCK_ID", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "CATEGORY_ID",
nullable = false, updatable = false) })
public Set<Category> getCategories() {
return this.categories;
}
Category
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "categories")
public List<Stock> getStocks() {
return this.stocks;
}
When I tried to list all categories and your stocks I was getting Lazy Load exception - no session or session was closed.
So I changed my method to initialize all stocks from every category. If I want to initialize another entity I just put it inside for loop:
session = HibernateUtil.getSessionFactory().openSession();
Criteria cri = session.createCriteria(Category.class)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
List<Category> categories = (List<Category>) cri.list();
for (Category c :categories) {
Hibernate.initialize(c.getStocks());
}
But I get an SQL for every Category to initialize stocks and I'm thinking this is not good.
So, I tried to use .setFetchMode("stocks", FetchMode.JOIN) and I'll be getting one SQL but if I want use fecthmode and need to join with another entity i'll getting "cannot simultaneously fetch multiple bags".
Product
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "product_category" , joinColumns = {
@JoinColumn(name = "PRODUCT_ID", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "CATEGORY_ID",
nullable = false, updatable = false) })
public Set<Category> getCategories() {
return this.categories;
}
List:
session = HibernateUtil.getSessionFactory().openSession();
Criteria cri = session.createCriteria(Category.class)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.setFetchMode("stocks", FetchMode.JOIN)
.setFetchMode("products", FetchMode.JOIN);
I'm not convinced about which is the best way to do this using hibernate. I read a lot about OpenSessionInView but some suggest that is a bad pattern.
Upvotes: 0
Views: 478
Reputation: 21415
So I understand that your Category
entity is having ManyToMany
relationship with entities Stock
and also Product
. In your Category
entity, if you try to use List
for properties stocks
amd products
and then if you want to set the fetch mode to JOIN
as :
`criteria.setFetchMode("stocks", FetchMode.JOIN).setFetchMode("products", FetchMode.JOIN);`
then Hibernate throws an exception as:
org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
To fix this issue you have to change the type of properties for stocks
& products
to Set
instead of List
in your Category
entity class.
Upvotes: 2