问题
I'm using EclipseLink as JPA provider in a Java SE project. I have properly configured the weaving to allow the Lazy Loading.
Unlike Hibernate (which throws LazyInitializationException), EclipseLink can get a proxy of LAZY relationship, even with a closed EntityManager. To run this query, it gets a new connection from the pool.
Is there some setting that disables or changes the behavior of this feature? I need to get a null value or an exception when trying to access an unloaded attribute, such as Hibernate does.
Example:
List<Customer> customers = entityManager.createQuery("from Customer c", Customer.class).getResultList();
entityManager.close(); // Closing the EntityManager
for (Customer customer: customers) {
customer.getAddress(); // Here EclipseLink executes a query to get the relationship.
}
Thanks.
回答1:
EclipseLink allows you to access lazy relations, even when the EntityManager has been closed. This behaviour is EclipseLink-specific and not part of the JPA spec.
You will get the Exception you are looking for, when the Connection has been closed.
However, EclipseLink is wrapping not-instantiated Lists into IndirectList
. You are able to check programmatically if the List has been instantiated or not.
if(customers instanceof IndirectList) {
boolean foo = ((IndirectList) customers).isInstantiated();
// ...
}
See also:
- https://community.oracle.com/message/1708796
- https://eclipse.org/eclipselink/api/2.0/org/eclipse/persistence/indirection/IndirectList.html
回答2:
Pattern "jpa session in view" is Your friend. Basically: during cycle of request You open EntityManager (quite early or on request), dont close in your application code (all lazy element can be fetched) and automate close EM in one of last operations.
I had identical problem. Personally i use Wicket, replace
class MyWebRequestCycle extends RequestCycle {
... // extract from bigger project
protected void onEndRequest() {
super.onEndRequest();
if (em != null) {
if (em instanceof MyEntityManager) {
MyEntityManager em2 = (MyEntityManager) em;
em2.original.close();
} else
em.close();
em = null;
}
}
}
MyEntityManager
is proxy (almost generated in Eclpse) over opened in early stage EntityManager
. And 'if' above is because of start of application, it is not part of our discussion.
In other frameworks in adequate way. It depends on You.
Answer has two path: full JEE container (programmers code does nothing to open or close EM) and servlet containers. My answer is for the second.
Remark: word session in this pattern is not web Session or not Session in sense entry parameters of JPA engine. This is only word ;)
来源:https://stackoverflow.com/questions/32694355/jpa-eclipselink-lazy-loading-with-closed-entitymanager