Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[eclipselink-users] Reuse of JPA mapped object copy

Hello everyone,

 

I am using EclipseLink 1.0.1 and have the default implicit copy on read behavior enabled in my JDK 1.5 environment. What I have recently discovered was that copies of objects made previously are not being reused in certain situations, and I would like to create as few copies of my mapped objects as possible to reduce heap needed to hydrate and interrogate a given domain object graph.

 

Suppose I have the following simplified domain model with a one to many from C to A and a back pointing many to one from A to C :

 

public class C

{

    @Id

    private int id;

 

    @OneToMany(fetch=LAZY, mappedBy="c", cascade={ALL})

    private List<A> as;

    …

}

 

public class A

{

    @ManyToOne(fetch=LAZY)

    @JoinColumn(name="C_FK")

    private C c;

 

    public C getC() { return c; }

    …

}

 

Further, suppose I find a given instance of C with a simple primary key based JQPL query as depicted in the following code snippet :

 

EntityManager em = getEntityManager();

Query q = em.createQuery("SELECT c FROM C c WHERE c.id = :id");

q.setParameter("id", idOfInterest);

C result = (C) q.getSingleResult();

em.close();

 

1. After the call to em.close(), if I interrogate the A instances of the resulting C instance returned, I see that the C instance returned by each A instance’s getC() method is not the same as the original C instance returned. i.e.  someA.getC() == originalC is false. This I expect since the C instance becomes detached at the moment the EntityManager is closed.

 

2. However, if I instead interrogate the C’s A instances and perform the same interrogation prior to the em.close() call, I see the same results, which I am not expecting. I would expect that calling getC() on an instance of A would return the C result instance since the EntityManager is still open at that point in time and thus the C result instance is not yet detached.

 

3. Further, I find that if I mark both relationships as being EAGER, then all of the A instance’s getC() calls do in fact return the same C result reference. This happens when the interrogation happens prior to the em.close() call, and I would expect the same result after the C instance is detached since the relationships are fully hydrated.

 

Are all three of these test results to be expected?

 

I now need to further refine my question. In my domain model, there is also a OneToMany from A to B, and a back pointing ManyToOne from B to A. In terms of a typical object graph, a given C instance may have 30 A instances and of all of those A instances, could have hundreds or thousands of B instances in total. In my test object graph, the C instance has some 80 or so A instances and some 3000 or so B instances.

 

I could instead use Fetch Joins to express the desire to eagerly load the A and B instances, and leave those annotations specifying lazy loading, which of course would give me better control for eagerly loading those relationships on a use case by use case basis. However, that approach concerns me due to the “performance implications” noted at the top of page 206 of Mike Keith’s and Merrick Schincariol’s Pro EJB 3 book. Additionally, I have found that this technique also results in the back pointing C reference to be a different C reference than that originally read.

 

If I change the JPQL to instead look like :

 

SELECT c FROM C c JOIN c.as a JOIN FETCH c.as JOIN FETCH a.c JOIN FETCH a.bs WHERE c.id = :id

 

I do not see the same results as I saw in point 3 above, but the query does run fine otherwise. The same is true if I eliminate the JOIN FETCH a.c part of the above query as well. I should note that I have attempted this with batch reading being used for the A’s B instances as well.

 

Have I exhausted the techniques currently available to avoid the creation of “extra” domain object copies?

 

Thank you,

 

Doug Gschwind






The contents of this electronic mail message and any attachments are confidential, possibly privileged and intended
for the addressee(s) only. Only the addressee(s) may read, disseminate, retain or otherwise use this message. If
received in error, please immediately inform the sender and then delete this message without disclosing its contents
to anyone.

Back to the top