Community
Participate
Working Groups
AttributeChangeTracking events are not being cleared when em.refresh or a query forcing a refresh is called. For instance: Employee emp = em.find(Employee.class, id); emp.setFirstName("changed!"); em.refresh(emp); .. em.flush(); after the refresh, emp.getFirstName will show the old string, but "changed!" will be updated in the database on the flush call. Worse, if a OneToOne/ManyToOne relationship is nulled out: Employee emp = em.find(Employee.class, id); emp.setManager(null); em.refresh(emp); .. em.flush(); This results in a NullPointerException on the flush or transaction commit: java.lang.NullPointerException at org.eclipse.persistence.mappings.ObjectReferenceMapping.update(ObjectReferenceMapping.java:1085) at org.eclipse.persistence.mappings.ObjectReferenceMapping.preUpdate(ObjectReferenceMapping.java:590) at org.eclipse.persistence.descriptors.DescriptorQueryManager.preUpdate(DescriptorQueryManager.java:1089) at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:1121) at org.eclipse.persistence.queries.UpdateObjectQuery.executeCommitWithChangeSet(UpdateObjectQuery.java:84) at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:291) at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58) at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:808) at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:711) at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108) at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2842) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1521) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1503) at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1463) at org.eclipse.persistence.internal.sessions.CommitManager.commitChangedObjectsForClassWithChangeSet(CommitManager.java:265) at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:128) at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:3766) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1404) at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:616) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithPreBuiltChangeSet(UnitOfWorkImpl.java:1552) at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:427) at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:743)
Actual sequence of steps to see the issue (object uses attribute level change tracking) Read a Change a.b Refresh a Change a.c flush change to a.b is written The issue here is that the ChangeSet created by Attribute Level Change tracking is also stored as part of the unit of work change set. The UnitOfWork version of this is not cleared by the refresh. When the 2nd change is made, we look up the change set in the unit of work and use it. The change from prior to the refresh is still there.
Created attachment 187872 [details] Proposed fix Proposed fix clears the ObjectChangeSet when a clear is called for revert
Created attachment 187874 [details] Updated fix - 2.2 stream
Created attachment 187997 [details] Updated Patch - 2.2 stream
Changes checked into 2.2 - rev 8906 Code is changed to clear the object change set associated with the AttributeChangeListener prior to nulling it out during a refresh Added 3 tests to EntityManagerJunitTestSuite Tested with Core and JPA LRG Reviewed by Gordon Yorke
Checked into trunk
See: Bug 356627 - Backport Bug 335322 - AttributeChangeTracking: change events not cleared when refresh is called to 2.1.
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink