Reputation: 31
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.
Upvotes: 3
Views: 1652
Reputation: 86
There seems to be no setting for that, but you could clear the session explicitly after detaching the entity: ((FetchGroupTracker)entity)._persistence_setSession(null)
.
See also https://github.com/eclipse-ee4j/eclipselink/blob/7dfeab504e7b0042e6330315297bed0e6739cc95/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/queries/FetchGroup.java#L165 regarding how this is implemented.
Upvotes: 1
Reputation: 2797
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:
Upvotes: 4
Reputation: 1906
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 ;)
Upvotes: 0