Community
Participate
Working Groups
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!
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().
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.
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).
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?
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.
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.
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.
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink