3

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.

3 Answers3

4

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:

stg
  • 2,757
  • 2
  • 28
  • 55
  • Thank you, but in my case is a ManyToOne relationship. I've tried checking with Persistence.getPersistenceUtil().IsLoaded() method, but neither worked. – Rodolpho Couto Sep 21 '15 at 13:57
0

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 ;)

Jacek Cz
  • 1,872
  • 1
  • 15
  • 22
  • Thanks, but this pattern does not solve my problem. I need EclipseLink not make queries to return LAZY relationships, I need it returns null. – Rodolpho Couto Sep 21 '15 at 13:51
  • I would advise against "open session in view": http://blog.jhades.org/open-session-in-view-pattern-pros-and-cons/ https://blog.frankel.ch/the-opensessioninview-antipattern It's considered an antipattern in Hibernate and I doubt EclipseLink considers it much better. – Jose Ferrer Dec 15 '15 at 00:54
0

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.

Thomas
  • 11
  • 2