Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 319162

Summary: EntityManager found stale entity after flush and clear
Product: z_Archived Reporter: Daniel Lo <daniel.lo>
Component: EclipselinkAssignee: Nobody - feel free to take it <nobody>
Status: CLOSED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: douglas.clarke, eclipselink.orm-inbox, SebTardif, tom.ware
Version: unspecified   
Target Milestone: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Attachments:
Description Flags
event-listener work-around with supporting test cases
none
Proposed fix - EclipseLink 2.1 stream
none
Updated patch none

Description Daniel Lo CLA 2010-07-07 12:55:35 EDT
Build Identifier: 2.0.2.v20100323-r6872

In J2EE environment, within a transaction, after we updated an entity, we invoked the EntityManager.flush() then the EntityManager.clear() API, before we commit the transaction, we did a EntityManager.find() which returned the previous entity version before the update, this seems to a bug, since the changes have been flushed to the database, the EntityManager.find() should retrieve and return the latest version instead of the previous version.

Here is the test code and the logs:

UserTransaction ut = getTransaction();
ut.begin();
EntityManager em = getEntityManager();
System.out.println("1. ***** Before merge: isManaged = " + em.contains(dataTypes) +
" version = " + dataTypes.getEntityVersion() + " aString = " + dataTypes.getAString());
dataTypes.setAString("999");
dataTypes = em.merge(dataTypes);
em.flush();
System.out.println("2. ***** After flush: isManaged = " + em.contains(dataTypes) +
" version = " + dataTypes.getEntityVersion() + " aString = " + dataTypes.getAString());
em.clear();
System.out.println("3. ***** After clear: isManaged = " + em.contains(dataTypes) +
" version = " + dataTypes.getEntityVersion() + " aString = " + dataTypes.getAString());

dataTypes = (DataTypes)em.find(DataTypesDAO.class, dataTypes.getEntityId());
System.out.println("4. ***** After find by PK: isManaged = " + em.contains(dataTypes) +
" version = " + dataTypes.getEntityVersion() + " aString = " + dataTypes.getAString());

ut.commit();

ut = getTransaction();
ut.begin();
em = getEntityManager();
dataTypes = (DataTypes)em.find(DataTypesDAO.class, dataTypes.getEntityId());
System.out.println("5. ***** After find by PK: isManaged = " + em.contains(dataTypes) +
" version = " + dataTypes.getEntityVersion() + " aString = " + dataTypes.getAString());
ut.commit();

1. ***** Before merge: isManaged = false version = 7 aString = 888
2. ***** After flush: isManaged = true version = 8 aString = 999
3. ***** After clear: isManaged = false version = 8 aString = 999
4. ***** After find by PK: isManaged = true version = 7 aString = 888
5. ***** After find by PK: isManaged = true version = 8 aString = 999

Reproducible: Always

Steps to Reproduce:
1. See test code in Details section
Comment 1 Doug Clarke CLA 2010-07-08 12:31:14 EDT
Created attachment 173786 [details]
event-listener work-around with supporting test cases
Comment 2 Doug Clarke CLA 2010-07-08 12:31:42 EDT
This issue was reproduced in 2.1.0
Comment 3 Tom Ware CLA 2010-08-09 14:29:28 EDT
Triaging.
Comment 4 Tom Ware CLA 2010-08-09 15:10:07 EDT
Is it possible to provide the persistence unit that recreates this problem?
Comment 5 Tom Ware CLA 2010-08-11 15:47:14 EDT
Created attachment 176392 [details]
Proposed fix - EclipseLink 2.1 stream
Comment 6 Tom Ware CLA 2010-08-11 15:54:12 EDT
The patch above causes objects that could be changed in a cleared unit of work to be constructed in the UnitOfWork directly from the database forgoing the SharedCache.  The behavior will be different depending on your settings for FLUSH_CLEAR_CACHE on your EntityManager.

For FlushClearCache.Drop - As indicated in the documentation, you will get objects from teh shared cache

For FlushClearCache.DropInvalidate(default) - We will build from the databse to the unit of work, if the class of the object being queried is set to be invalidated due to the call to clear

For FlushClearCache.Merge - We will build from the database to the unit of work if the class of the object being queried is included in the cumulative change set created as a result of the call to clear.  Note: Although it would be possible to identify individual objects in the change set, we are dealing with queries that may not be querying by PK and therefore must consider the possibility that all objects of a particular class are affected. (Unfortunately our default readFromDB to UOW functionality does not help us because it only applies to Native queries and Update All queries)
Comment 7 Tom Ware CLA 2010-08-12 13:25:50 EDT
Created attachment 176485 [details]
Updated patch
Comment 8 Tom Ware CLA 2010-08-16 11:37:57 EDT
Checked into trunk
Similar fix will be put in 2.1.2 when the stream opens

A fix was checked in to have Object build directly to the UOW in the case that a clear has been run with certain FlushMode settings

Reviewed by Gordon Yorke

Added 3 tests to the EntityManagerJunitTestSuite for the annotations model
Comment 9 Tom Ware CLA 2010-08-27 09:30:51 EDT
Fix checked into 2.1.2
Comment 10 Eclipse Webmaster CLA 2022-06-09 10:21:48 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink