Community
Participate
Working Groups
There are several scenarios where the query cache can miss results. 1. The call to ReadQuery.cacheResult() is only made for objects that are not found in the unit of work. That means that if you query for an object with an EAGER self-referencing relationship, it is possible objects will be missed. You can see this in the relationship between Employee->manager when running AdvancedQueryTestSuite.testQueryCache() with weaving turned off. The result of the 2nd run of "CachedAllEmployees" will not be the same as the result of the 1st run of "CachedAllEmployees" because the manager relationship will cause some Employees to be registered in the unit of work before they can be cached. Note: To see this issue in an IDE, you will have to turn off expiry on the CachedAllEmployees query. The code that causes this issue can be found in the object builder methods buildObject(), and buildWorkingCopyCloneNormally(). Notice that "found" objects are never candidates to be cached(). 2. It appears as though objects in an early transaction will have the same issue. To solve this issue, we will have to make sure that all the various pathes a query can go down have calls to cacheObject in appropriate places. Some parts of this issue are a regression based on changed code in the 2.1 stream (e.g. #1 above). Others may have existed for longer.
Another repro for this issue in testuite eclipselink.jpa.wdf.test: org.eclipse.persistence.testing.tests.wdf.jpa1.query.TestSimpleQuery.testCachedQueryWithoutClear to activate the test, add the property test.bugzilla.run=301063 in the test.properties. If fixed, please remove the @Bugzilla annotation.
Looking into this. Will fix in 2.1. The early transaction issue can be resolved by setting @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE_IGNORE_NULL, value="true") on the query.
Just looked at the javadoc of QUERY_RESULTS_CACHE_IGNORE_NULL: /** * "eclipselink.query-results-cache.ignore-null" * <p>Configures null results to not be cached. * This can be used to use the query cache as a secondary key index, and allow inserts of new objects. * By default null results are cached. * Valid values are number of milliseconds, Integer or Strings that can be parsed to int values. * @see org.eclipse.persistence.queries.QueryResultsCachePolicy#setIsNullIgnored(boolean) */ public static final String QUERY_RESULTS_CACHE_IGNORE_NULL = "eclipselink.query-results-cache.ignore-null"; Please also touch up "Valid values" ;-).
Found some other cases, If descriptor was isolated (no cache) then objects are built in unit of work, and never cache, so empty collection is put in query cache. The code already handle putting isolated cache objects in the isolate cache, but only if the object were built in the isolated session, not the unit of work. Will fix to not cache queries if they do not build objects in the session (server or isolated). Note that by default is shared=false, objects will always be built in the unit of work (unless a read-only query), so the query cache will not be used. The descriptor uow isolation flag can be set to build objects in the session if query caching is desired, but note that the query cache will only live as long as the isolated session.
Created attachment 157784 [details] fix to query cache, also include changes for jpacache
Fixed
SVN main commit: Bug#301063 - fix to query cache, jpa cache interface and extensions https://bugs.eclipse.org/bugs/show_bug.cgi?id=301063 https://bugs.eclipse.org/bugs/show_bug.cgi?id=298985 Doc, http://wiki.eclipse.org/EclipseLink/DesignDocs/298985 Changes: - Fixed java doc on query hints for query cache. - Added check for CacheKeyType.AUTO, and exception for invalid type to descriptor. - Ensure session cache object is built when using query cache, so it can be cached. - Fixed validateCache() to work for descriptors that are not cached (aggregates). - Changed query cache method to take List instead of Vector for params. - Removed some duplicate code in olr query. - Ignore null temp result is query cache (objects not built in session cache), use invalid object to represent null/empty. - Added tests for new JpaCache API. - Added tests for query caching inside uow of work and early transaction. - Added extended cache API to JPA Cache, added JpaCache interface. Code review: Andrei, Gord
The patch fixes the issue with org.eclipse.persistence.testing.tests.wdf.jpa1.query.TestSimpleQuery.testCachedQueryWithoutClear. However, unfortunately, it is causing a new issue with the server tests on NetWeaver: java.lang.NoSuchMethodError: javax.persistence.EntityManagerFactory.getCache()Ljavax/persistence/Cache; at org.eclipse.persistence.testing.tests.jpa.jpql.AdvancedQueryTestSuite.testQueryCache(AdvancedQueryTestSuite.java:781) at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.runBareServer(JUnitTestCase.java:489) at org.eclipse.persistence.testing.framework.server.TestRunnerBean.runTest(TestRunnerBean.java:87) at com.sap.engine.services.ejb3.runtime.impl.RequestInvocationContext.proceedFinal(RequestInvocationContext.java:47) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:166) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatesTransition.invoke(Interceptors_StatesTransition.java:19) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Resource.invoke(Interceptors_Resource.java:47) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Transaction.doWorkWithAttribute(Interceptors_Transaction.java:37) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_Transaction.invoke(Interceptors_Transaction.java:21) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_MethodRetry.invoke(Interceptors_MethodRetry.java:46) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:189) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_StatelessInstanceGetter.invoke(Interceptors_StatelessInstanceGetter.java:16) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_SecurityCheck.invoke(Interceptors_SecurityCheck.java:25) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.Interceptors_ExceptionTracer.invoke(Interceptors_ExceptionTracer.java:17) at com.sap.engine.services.ejb3.runtime.impl.AbstractInvocationContext.proceed(AbstractInvocationContext.java:177) at com.sap.engine.services.ejb3.runtime.impl.DefaultInvocationChainsManager.startChain(DefaultInvocationChainsManager.java:138) at com.sap.engine.services.ejb3.runtime.impl.DefaultEJBProxyInvocationHandler.invoke(DefaultEJBProxyInvocationHandler.java:164) at com.sap.engine.services.ejb3.runtime.impl.RemoteEJBProxyInvocationHandler.invoke(RemoteEJBProxyInvocationHandler.java:98) NetWeaver is a JPA 1.0 server and the JPA 2.0 API and hence the emf.getCache() method is not visible. As far as I know, this issue exists on other severs as well.
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink