3

I am running a test on eclipselink JPA 2, to determine how lazy loading of a collection is working. I have assumed, the if you load an entity, then all eager elements are loaded first of all, then, within the JPA session, the lazy elements are loaded when you ask for them, or touch them (refer to them in some way, like getting the size of a lazy collection). The problem I have is this: when I detach the entity from the session, the lazy collection is loaded, and is available, even though I didn't ask for it?? I either mis-understand the JSR, or this is normal behaviour in eclipselink. From using hibernate, I know this does not happen.

EntityManager em = emf.createEntityManager();
        AloadTest at1 = em.find(AloadTest.class, pkLazy);

        serializeObject(at1,"InSessionLazy");

        em.detach(at1);
        em.close();

If I run this in a debug, and watch my lazy elements, I can see they are not loaded when I access my 'at1' object, but the minute I step over the em.detach(at1) line, the lazy entities are loaded.

I have a defined lazy collection in my AloadTest C.D. as such:...

@OneToMany(fetch = javax.persistence.FetchType.LAZY, cascade = CascadeType.PERSIST, /*, cascade = CascadeType.ALL, */mappedBy = "aloadtest")
    public Set<CloadLazyMultitest> getCloadLazyMultitest() {
        return cloadLazyMultitest;
    }
    public void setCloadLazyMultitest(Set<CloadLazyMultitest> cloadLazyMultitest) {
        this.cloadLazyMultitest = cloadLazyMultitest;
    }

Thanks in advance, but I do not think my lazy collection should be loaded if I havent asked for it.

EDIT: I did your test James, and your are correct about the indirection test:

logger.info(" ARE WE LAZY LOADED BEFORE :"+((IndirectSet)at1.getCloadLazyMultitest()).isInstantiated()); 

        em.detach(at1);

        logger.info(" ARE WE LAZY LOADED AFTER :"+((IndirectSet)at1.getCloadLazyMultitest()).isInstantiated()); 

And the output to my logger:

17:14:16.707 [main] INFO  c.c.t.j.t.JpaI3EagerAndLazyLoadingTest -  ARE WE LAZY LOADED BEFORE :false

17:14:16.723 [main] INFO c.c.t.j.t.JpaI3EagerAndLazyLoadingTest - ARE WE LAZY LOADED AFTER :true

My point is? why am I getting lazy collections loaded, I dont ask for the collection, just the parent entity. What would happen if I had a chain of 2 or 10 collections, each annotated as a lazy collection? I think it would be quite an overhead. Its never been an issue before with Hibernate, but as eclipselink is now the JPA refernce, I have to build a solution based on this.

Surely its ok to detach an object, to make it 'dirty', do some processing and re-attach to a new session. I am thinking more in a 'long conversation' environment, probably stateless session beans and a web front?

kevin the kitten
  • 344
  • 1
  • 2
  • 8
  • Are you sure it's not the debugger that calls methods of you collection behind your back (its toString method, for example)? What does the serializeObject method do? – JB Nizet Dec 13 '11 at 14:13
  • The serialize object serializes my object, straight away, when I deserialize this object, it does not contain the lazzy loaded collection, which is as expected. Its not the debugger, because I loop on the detached object latter on in the code, and the collection is loaded. IE. this behavior of automatically loading the collection happened before I sent it through the debugger. – kevin the kitten Dec 13 '11 at 14:45

2 Answers2

3

In looking at the latest EclipseLink code, it doesn't seem like detach() will trigger the lazy collection. Are you should detach is triggering it?

In general EclipseLink allows you to access LAZY relationships after closing the EntityManger, so even though you detached the object, it will still have access to the relationships (unless you serialize it).

You can check if the relationship is instantiated using,

((IndirectSet)at1.getCloadLazyMultitest()).isInstantiated()

Check this before and after the detach() call.

I'm not sure why you are using detach, it is a pretty rare method, it basically can be used to expel an object from the persistence context to avoid its changes being written to the database.

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
James
  • 17,965
  • 11
  • 91
  • 146
  • Hi, I am using the detach method in a standalone J2SE environment, to assess the merits of eclipselink for an up-coming project. I suppose we will be using a Stateless session bean for accessing our objects in the real environment. – kevin the kitten Dec 13 '11 at 16:18
  • My boss gave me a checklist, and I am ticking them off, the LazyLoad test, says I should get a session, get an object, detach the object, query the lazy collection, and it should throw an error. – kevin the kitten Dec 13 '11 at 16:20
  • Hi James, I did your test on indirection, and have edited the original question. – kevin the kitten Dec 14 '11 at 08:50
2

EclipseLink allows loading lazy relationships as long as the connection is still available, as described here: http://forums.oracle.com/forums/thread.jspa?messageID=1706796

Chris
  • 20,138
  • 2
  • 29
  • 43
  • Hi Chris, I read the link, and it still seems strange that a collection is lazy loaded even though you havent asked for it, IE. at the point of detachment. – kevin the kitten Dec 14 '11 at 08:48
  • Does your entity implement a toString method that accesses lazy relationships? This would cause it to be triggered when logging is enabled, and is generally not recommended. – Chris Dec 14 '11 at 21:58
  • Hi Chris, no I dont override toString(), or print out the contents of the lazy collection in any place other then the test case. – kevin the kitten Dec 15 '11 at 19:57
  • what do you mean as long as the connection is available ? – Ced Jun 30 '16 at 03:56