Hibernate is create an extra select query to map collections on an entity merge operation

Solution Verified - Updated -

Environment

  • JBoss Enterprise Application Platform (EAP) 5.1
  • Hibernate 3.3

Issue

  • We are  seeing one extra select query to Map Collections after a merge operation on the owning entity.  The map was not modified so there is nothing to change, and if session.update instead of merge is used, there is no extra select query.
  • During the merge operation the map collections become dirty, due to this the additional select is triggered:

    TestManagerNew [Java Application]   
      at test.TestManagerNew at localhost:40513   
      at Thread [main] (Suspended (breakpoint at line 191 in PersistentMap))   
      at PersistentMap.put(Object, Object) line: 191   
      at MapType.replaceElements(Object, Object, Object, Map, SessionImplementor) line: 98   
      at MapType(CollectionType).replace(Object, Object, SessionImplementor, Object, Map) line: 574   
      at TypeFactory.replace(Object[], Object[], Type[], SessionImplementor, Object, Map) line: 505   
      at DefaultMergeEventListener.copyValues(EntityPersister, Object, Object, SessionImplementor, Map) line: 496   
      at DefaultMergeEventListener.entityIsDetached(MergeEvent, Map) line: 424   
      at DefaultMergeEventListener.onMerge(MergeEvent, Map) line: 234   
      at DefaultMergeEventListener.onMerge(MergeEvent) line: 84   
      at SessionImpl.fireMerge(MergeEvent) line: 706   
      at SessionImpl.merge(String, Object) line: 690   
      at SessionImpl.merge(Object) line: 694   
    

Resolution

In order to merge the map per JPA definition Hibernate has to know its current "persistent" state.  However, as the owner and collection are detached, the only known "persistent state" is the database.  This is true for merge in general.

update() is a different case, with different semantics.  It assumes that things reattached are dirty and will always result in updates.

This is all logical and consistent if you step back and think about the fact that update() does not return a new instance while merge() does.

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Close

Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.