This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
Bug 301063 - Query Cache missing results
Summary: Query Cache missing results
Status: RESOLVED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-01-27 15:28 EST by Tom Ware CLA
Modified: 2022-06-09 10:23 EDT (History)
4 users (show)

See Also:


Attachments
fix to query cache, also include changes for jpacache (100.90 KB, patch)
2010-02-01 10:02 EST, James Sutherland CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tom Ware CLA 2010-01-27 15:28:29 EST
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.
Comment 1 Adrian Goerler CLA 2010-01-28 07:43:25 EST
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.
Comment 2 James Sutherland CLA 2010-01-28 10:17:39 EST
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.
Comment 3 Adrian Goerler CLA 2010-01-28 10:23:03 EST
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" ;-).
Comment 4 James Sutherland CLA 2010-01-28 13:12:55 EST
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.
Comment 5 James Sutherland CLA 2010-02-01 10:02:36 EST
Created attachment 157784 [details]
fix to query cache, also include changes for jpacache
Comment 6 James Sutherland CLA 2010-02-01 10:09:35 EST
Fixed
Comment 7 James Sutherland CLA 2010-02-01 10:25:37 EST
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
Comment 8 Adrian Goerler CLA 2010-02-01 11:56:19 EST
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.
Comment 9 Eclipse Webmaster CLA 2022-06-09 10:23:39 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink