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

Bug 363136

Summary: Strange cache behaviour after clear/flush
Product: z_Archived Reporter: Tom Bailey <geeky.diamond>
Component: EclipselinkAssignee: Project Inbox <eclipselink.orm-inbox>
Status: NEW --- QA Contact:
Severity: major    
Priority: P2 CC: christopher.delahunt, geeky.diamond, tom.ware
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows 7   
Whiteboard:
Attachments:
Description Flags
A basic entity that recreates the problem none

Description Tom Bailey CLA 2011-11-08 04:34:45 EST
Build Identifier: 2.3.0

We are using glassfish 3.1.1 (with eclipselink 2.3.0) and are having a strange problem with the cache on the entity manager.
Basically we want to detach entities before sending them to subsystems. It is the case (quite often) that the same entity can be changed twice within one transaction (by two different subsystems) and this multiple update of detached entities seems to expose an issue with the entity manager cache.
A simple example that exposes the problem is in the code below:
DataObject dataObject = entityManager.find(DataObject.class, dataObjectId);
entityManager.clear();
// First update
dataObject.setNotes("Notes 1");
entityManager.merge(dataObject);
// Simulate query implicit flush
entityManager.flush();
// Re-retrieve the entity
dataObject = entityManager.find(DataObject.class, dataObjectId);
// Detach again
entityManager.clear();
// Next update
dataObject.setNotes("Notes 2");
entityManager.merge(dataObject);
This code when run many times will alternately persist "Notes 1" to the database followed by "Notes 2" followed by "Notes 1" etc. However, if the code is changed so that the number after Notes increments every time then the correct value is always persisted. Therefore, it looks like the cache isn't updated after the first merge, so if the second merge has the same value as the object in cache then no merge takes place (leaving "Notes 1" on the object being persisted to the database).
The reason for the flush is because a query between the two updates would invoke an implicit flush. Without the flush the problem does not occur, so the flush seems to clear the entity manager cache back to the original state, rather than the state flushed to the database.

Adding a cache evict fixes the code:
DataObject dataObject = entityManager.find(DataObject.class, dataObjectId);
entityManager.clear();
// First update
dataObject.setNotes("Notes 1");
entityManager.merge(dataObject);
entityManager.getEntityManagerFactory().getCache().evict(DataObject.class, dataObject.getId());
// Simulate query implicit flush
entityManager.flush();
// Re-retrieve the entity
dataObject = entityManager.find(DataObject.class, dataObjectId);
// Detach again
entityManager.clear();
// Next update
dataObject.setNotes("Notes 2");
entityManager.merge(dataObject);
but it makes the system a lot slower to run and adds a requirement that the developer remembers to do an evict after every merge

Reproducible: Always

Steps to Reproduce:
1.Run code in details above
2.Note the value in the database is Notes 2
3.Run the code in details above again
4.Note the value in the database is now Notes 1!
Comment 1 Tom Bailey CLA 2011-11-08 04:36:17 EST
This bug was originally posted in the forum and 'James' replied with:
The cache should not be updated after the merge, it can only be updated after the commit. But the second find should not hit the cache, this seems to be a bug, please log the bug.

If you remove the clear(), then the issue will not occur (and calling clear in the middle of a transaction is not normally a good idea). Also you could call refresh() instead of find() (or call find() with the refresh property).

My guess is that it would not occur with a Query, only with find().
Comment 2 Chris Delahunt CLA 2011-11-08 12:33:40 EST
Can you simplify the problem?  What seems suggested is that the value in the field when you do the second find is not "Notes 1" but the value that was there before the flush.  Can you verify that this is the problem, and send in a reproducable test case?  A test case would help in case there is a problem reproducing it due to specific settings on your entities or in your environment that contribute to the issue.
Comment 3 Tom Bailey CLA 2011-11-09 07:44:41 EST
Debugging the code it is all correct. The DataObject retrieved in the second find has the correct notes field (i.e. Notes 1). This seems to be the minimal code required to reproduce the problem (it took ages to track down because debugging the code doesn't help, the issue is what is actually sent to the database).
Comment 4 Chris Delahunt CLA 2011-11-09 11:12:10 EST
We will need more information to reproduce then, as if the data on the find is correct, it is not hitting the cache as was suspected.  

Is the entity set any of its basic attributes to be lazy or configured a fetch group?  Can you provide the entity and any setting you have that reproduce the problem?
Comment 5 Tom Bailey CLA 2011-11-09 11:44:07 EST
Created attachment 206714 [details]
A basic entity that recreates the problem

The problem seems to happen with any entity. Attached is a basic entity that I have recreated the problem on.
Comment 6 Tom Bailey CLA 2011-11-09 11:48:53 EST
Background information: We are using Oracle 11g with ojdbc6 driver jar. Our glassfish is running on Windows 7, although I believe we have seen the problem on our linux test boxes, so don't think os is the issue. We have specified no eclipselink properties in the ears, so using all default settings.
Comment 7 Tom Ware CLA 2011-11-17 13:48:32 EST
Setting target and priority.  See the following page for the meanings of these fields:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines

Community: Please vote for this bug if it is important to you.  Votes are one of the main criteria we use to determine which bugs to fix next.
Comment 8 Eclipse Webmaster CLA 2022-06-09 10:05:10 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink