EntityNotFoundException for already deleted entity during merge in JBoss EAP 6.4
Issue
- We have an application based on JSF 2, CDI, JPA/Hibernate, and we are porting it from EAP 6.0.1 to EAP 6.4.Actually we have encountered a problem on two related entities, Entity1, and Entity2. The Entity1 class owns a list of Entity2 objects.
@Entity
@Table(name = "ENTITY1" [...])
public class Entity1 [...]{
[...]
@OneToMany(mappedBy = "entity1", cascade = { CascadeType.PERSIST,CascadeType.MERGE, CascadeType.REFRESH })
private List<Entity2> testEntity2 = new ArrayList<Entity2>();
[...]
@Entity
@Table(name = "ENTITY2", uniqueConstraints = @UniqueConstraint(columnNames = {"test", "ID_ENTITY1_FK", "test_ENTITY2_FK" }))
public class Entity2 [...]
- In our use case modify Entity1, an Entity1 object is read from DB and managed in detached state by a conversation scoped CDI bean. During the use case, Entity2 objects can be inserted, updated and removed.At the end of the user transaction, changes are saved merging the Entity1 object.
- We can't use
orphanRemoval=trueto handle the delete of Entity2 objects because there is aUNIQUE constraintin ENTITY2 table, and in a single user transaction the user can delete and re-insert a Entity2 row with the same unique key. So, in the controller bean we handle a list of Entity2 objects to delete, and in the save() method we delete them before saving the main Entity1 object:
for (Entity2 ti : Entity1ModelBean.getEntity2()) {
if (ti.getId() != null) {
Entity2Dao.delete(Entity2Dao.findById(ti.getId()));
}
}
ent = Entity1Dao.merge(ent);
- Unfortunately, when there is a Entity2 object to delete, with
JBoss EAP 6.0all is OK, whileJBoss EAP 6.4fires a
javax.persistence.EntityNotFoundException during merge operation.
- The entity not found is a Entity2 object just deleted and NOT present in testEntity2 List of the main object.When tested
JBoss EAP 6.0.1 with (hibernate-core-4.1.6.Final-redhat-3.jar)Its works fine, but withJBoss EAP 6.4 with (hibernate-core-4.2.18.Final-redhat-2.jar)it throws below, this is a snippet from application log:
DEBUG AbstractDaoImpl.findById() - getting Entity2 instance with id: 10101
Hibernate: select [...] from ENTITY2 [..] where entity20_.ID=?
DEBUG AbstractDaoImpl.findById() - get successful, instance found
DEBUG AbstractDaoImpl.delete() - ###### deleting Entity2 [id=10101, ...]
DEBUG AbstractDaoImpl.delete() - ###### delete successful
Hibernate: delete from ENTITY2 where ID=? and VERSION=?
DEBUG AbstractDaoImpl.delete() - flushed!
DEBUG AbstractDaoImpl.merge() - ###### merging Entity1 [id=10101, ....]
Hibernate: select [...] from ENTITY2 [..] where entity20_.ID=?
ERROR AbstractDaoImpl.merge() - merge failed
javax.persistence.EntityNotFoundException: Unable to find Entity2 with id 10101
at org.hibernate.ejb.Ejb3Configuration$Ejb3EntityNotFoundDelegate.handleEntityNotFound(Ejb3Configuration.java:158)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:214)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:264)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1053)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:980)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:714)
at org.hibernate.type.EntityType.resolve(EntityType.java:502)
at org.hibernate.type.EntityType.replace(EntityType.java:366)
at org.hibernate.type.CollectionType.preserveSnapshot(CollectionType.java:558)
at org.hibernate.type.CollectionType.replaceElements(CollectionType.java:532)
at org.hibernate.type.CollectionType.replace(CollectionType.java:660)
at org.hibernate.type.TypeHelper.replace(TypeHelper.java:177)
at org.hibernate.event.internal.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:401)
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:338)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:180)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:86)
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:833)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:817)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:821)
at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:889)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
at $Proxy124.merge(Unknown Source)
- Going in debug mode, we saw that Entity2 with id 10101 is not present in main testEntity2 List, but is contained in the (hidden) storedSnapshot collection, and Hibernate tries to load it from DB in the CollectionType.preserveSnapshot() method. This method was not present in Hibernate version bundled with EAP 6.0.1
Environment
- Red Hat JBoss Enterprise Application Platform (EAP)
- 6.4.0
- Hibernate/JPA
Subscriber exclusive content
A Red Hat subscription provides unlimited access to our knowledgebase, tools, and much more.