users@glassfish.java.net

Re: JPA, Eclipselink, EJB and caching question

From: N W <emailnbw_at_gmail.com>
Date: Fri, 9 Sep 2011 20:13:57 -0400

Hi Mitesh,

I am indeed using EJB methods with the default TransactionAttribute of REQUIRED and both EJBs inject the same EntityManager. Setting the query hint "eclipselink.refresh" to true fetches the updated state because it tells Eclipselink to bypass the cache and rebuild the entity state directly from the DB. At that time the DB has the updated state so and this causes it to be picked up. The code which loops and updates state manually is calling flush() each time which is why the DB state is up to date even though the method hasn't finished/committed yet. The Eclipselink cache only updates on a commit as opposed to updating o a flush() as well so that is the reason for the behavior in that case.

In terms of the second case, where I am able to see the updated state by changing from a NamedQuery to a 'simple' query, I am guessing that this is due to the fact that NamedQueries leverage the cache / prepared statement cache and 'simple' queries do not. I am not sure about this as I haven't looked into the details of how 'simple' queries in Eclipselink are supposed to use the cache but that is my first guess.

In any event what I ended up doing was moving the code that does the merge operation which updates the property inside the loop to a separate method which is annotated with REQUIRES_NEW. This causes the cache and the DB to be updated when the property value changes so my NamedQuery fetch operation will see the updated value when it references the cache.

-Noah

On Sep 9, 2011, at 4:23 PM, Mitesh Meswani wrote:


>>
> Your assumption is correct here. The second EJB will not see the updates from first EJB till it commits. This is as intended to ensure "read-committed" semantics.
> I am not able to understand why you will observe the behavior you are describing below. (I am assuming that you are using container managed EM/EMF obtained from same persistence unit in both Class A and Class B and the method in Class A and the inject EJB is typical EJB method that has transaction attribute defaulted to REQUIRED)
>>
>> The only way I have been able to see this updated state is by doing one of the two following things:
>>
>> 1) Set the query hint "eclipse link.refresh" to true on the fetch query called by class B
>> 2) Change the query from a NamedQuery to simple a Query, eg. TypedQuery<Foo.class> q = entityManager.createQuery vs. entityManager.createdNamedQuery.
>>
>> However, doing either of these things forces a fetch from the DB which negates the in memory cache optimizations.
>>
>> Any insight would be appreciated. Thanks,
>>
>> -Noah