Skip to main content



      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 10:49 Go to next message
Eclipse UserFriend
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 03:04] by Moderator

Re: Locking and caching [message #1336767 is a reply to message #1336741] Tue, 06 May 2014 11:02 Go to previous messageGo to next message
Eclipse UserFriend
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 04:33 Go to previous message
Eclipse UserFriend
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: Wed Jul 23 16:47:10 EDT 2025

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

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

Back to the top