The problem with this approach is that you can have the N+1 effect.
Imagine that you have the following entity:
public class Person{
@OneToMany // default to lazy
private List<Order> orderList;
}
If you have a report that returns 10K of persons, and if in this report you execute the code person.getOrderList()
the JPA/Hibernate will execute 10K of queries. This is the N+1 effect, you will have no control about all the queries that will be executed.
Imagine now that Order is like below:
public class Order{
@OneToMany // default to lazy
private List<EmailSent> emailSentList;
}
Imagine now that you have a iteration with the person.getOrderList()
and for every Order order
you will do a order.getEmailSentList()
. Can you see the problem now?
For LazyInitializationException you can have some solutions:
- Use the OpenInSessionInView approach. You will need to create a WebFilter that will open and close the transaction. The problem with is the N+1 effect.
- Use the hibernate.enable_lazy_load_no_trans configuration, that is a hibernate and you will not be able to port your project to other JPA provider if needed. You also can have the N+1 effect.
- Use the EJB feature named PersistenceContext Extended. With this you will keep the context opened of several transactions. The problems are: N+1 effect can happen, use a lot of server memory (entities will stay managed)
- Use the FETCH in the query. With this approach you could do a JPQL/HQL like:
select p from Person p join fetch p.orderList
. With this query you will have your list loaded from the database and will not have the N+1 effect. The problem is that you will need to write a JPQL for each case.
If you still have any problem, check these links:
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…