1
votes

I have a JAX-RS resource class. It invokes a stateless EJB which loads an entity (let's call it Parent).

Parent has a @ManyToOne relationship with another entity (let's call it Child) and is configured as having a fetch type of LAZY.

No additional transactional annotations appear on anything, so the stateless EJB has the default behavior of starting a transaction when necessary, and committing the transaction once its business method has completed.

In a debugger, I observe that Parent as returned by the EJB has null as the value of Child, just as I'd suspect. Lazy loading therefore is working fine.

My resource class then builds a Response and hands off control to the JAX-RS innards. Again, no transaction is open.

After serialization, the JSON (in my case) that shows up contains all the fields of Child. Something in the JAX-RS innards is somehow "inflating" that Child reference outside of the transaction.

I observe in a debugger that indeed at some point well after JAX-RS has taken over control that the Child reference has become non-null.

I thought that either Child should have stayed null or that an exception of some kind should have been thrown to indicate that someone tried to access a lazy-loaded field. Clearly I misunderstood something.

Under what circumstances may a detached JPA entity have its lazily-loaded relationships "inflated" outside of a transaction?

If it matters, I'm using Jersey 2.10.4 by way of Glassfish 4.1 and EclipseLink 2.5.2 (again, by way of Glassfish 4.1).

2
Perhaps I'm seeing EclipseLink-specific behavior? This question seems to be relevant.Laird Nelson

2 Answers

0
votes

if its truly "detached" then there is no context, hence no loading. If it is still in context then clearly it can load fields. This is according to the JPA spec.

Unless of course you're using some vendor-specific option, then you aren't following the JPA spec so can't rely on it in any other JPA implementation ...

0
votes

There is no need to start a transaction if you are only reading entities. For example the following code does not require transaction:

ParentEntity pe = entityManager.find(ParentEntity.class,1);
List<ChildEntity> childs = pe.getChildList();
System.out.println(childs.size());

However, please keep in mind that, as long as you are outside of transaction you will be unable to persist any changes to those entities.