kevin the kitten
kevin the kitten

Reputation: 344

Eclipselink Lazy Loading

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?

Upvotes: 3

Views: 12114

Answers (2)

James
James

Reputation: 18379

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.

Upvotes: 3

Chris
Chris

Reputation: 21145

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

Upvotes: 2

Related Questions