Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » PersistenceContext bypassed by EntityManager.find()(Disabling second level cache after lock() is used)
PersistenceContext bypassed by EntityManager.find() [message #1336741] Tue, 06 May 2014 14:49 Go to next message
Erik Brakkee is currently offline Erik BrakkeeFriend
Messages: 4
Registered: June 2011
Junior Member
Hi,


We are using eclipselink 2.5.1 in our application. In one case the EntityManager.lock() method is used for synchronizing on a heavily used object. We have enabled the second level cache for all objects. Now, what seems to happen is that a thread that is waiting in the lock() method, sometimes gets stale data after obtaining the lock.

What we think might be happening is that data is retrieved from the second level cache after the lock is obtained. Now we do want to have second level caching enabled as much as possible, but in these cases with locking we would like to disable the second level cache after the lock has been acquired.

We are currently doing this using

em().setProperty("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS)

(where em() returns the entity manager).

This is supposed to bypass the second level cache for all find operations so in that case we should not be getting stale data but current data from the first level cache (persistence context), and if not present there from the database.

However, we are now seeing some surprising behavior, which is that immediately after doing a persist of an entity such as

id = ... // determine primary key
T object = new T();
object.setId(id);
em().persist(object);

Then an em().find() operation is returning null.

T retrieved = em().find(T.class, id());

Only if we do a flush() right after the persist(), then we get the correct entity.

This is confusing since, if I read the specs correctly, the CacheRetrieveMode should bypass only the second level cache. Strangely enough, it looks like the persistence context is also being bypassed.

What could be wrong here?

The persistence XML is attached. Note that it is a 1.0 persistence XML which is required since we are (still) deploying on an old application server (JBoss 5.1).

Cheers
Erik


[Updated on: Thu, 08 May 2014 07:04]

Report message to a moderator

Re: Locking and caching [message #1336767 is a reply to message #1336741] Tue, 06 May 2014 15:02 Go to previous messageGo to next message
Erik Brakkee is currently offline Erik BrakkeeFriend
Messages: 4
Registered: June 2011
Junior Member
Note that since we are running in a JPA 1.0 environment, we cannot call em().setProperty() directly as I mentioned above but we have to use the following:

em().getDelegate().getClass().getMethod("setProperty", String.class, Object.class).invoke(em().getDelegate(), "javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
Re: Locking and caching [message #1340925 is a reply to message #1336767] Thu, 08 May 2014 08:33 Go to previous message
Erik Brakkee is currently offline Erik BrakkeeFriend
Messages: 4
Registered: June 2011
Junior Member
I have done some debugging and what I see happening is that the CacheRetrieveMode=BYPASS setting is being processed in QueryHintsHandler.CacheRetrieveModeHint.applyToDatabaseQuery()

if (query.isObjectLevelReadQuery()) {
                if (valueToApply.equals(CacheRetrieveMode.BYPASS) || valueToApply.equals(CacheRetrieveMode.BYPASS.name())) {
                    query.retrieveBypassCache();
                }

                // CacheRetrieveMode.USE will use the EclipseLink default of 
                // shouldCheckDescriptorForCacheUsage which in most cases is CheckCacheByPrimaryKey.
            } else {
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-type-for-query-hint",new Object[]{getQueryId(query), name, getPrintValue(valueToApply)}));
            }


Now, subsequenlty, when doing the find() operation, the cache is bypassed completely in ReadObjectQuery.checkEarlyReturnLocal(),

 if (shouldCheckCache() && shouldMaintainCache() && (!shouldRefreshIdentityMapResult() && (!shouldRetrieveBypassCache()))
                && (!(session.isRemoteSession() && (shouldRefreshRemoteIdentityMapResult() || this.descriptor.shouldDisableCacheHitsOnRemote())))
                && (!(shouldCheckDescriptorForCacheUsage() && this.descriptor.shouldDisableCacheHits())) && (!this.descriptor.isDescriptorForInterface())) {
            Object cachedObject = getQueryMechanism().checkCacheForObject(translationRow, session);
...
    }     


Here shouldRetrieveBypass is set to true by the query.retrieveBypassCache() hint.

Previous Topic:CursoredStream or ScrollableCursor with Native Query and SqlResultSetMapping?
Next Topic:JPQL LEFT JOIN FETCH Results in NPE when DescriptorCustomizer in Place
Goto Forum:
  


Current Time: Fri May 29 12:50:30 GMT 2015

Powered by FUDForum. Page generated in 0.03955 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software