hibernate - Optimistic locking while deleting entities in JPA -


a transactional method in ejb using cmt removes an entity supplied :

public boolean delete(entity entity) {     entity managedentity = entitymanager.find(entity.class, entity.getid());      if (managedentity == null) {         throw new entitynotfoundexception();     }      entitymanager.remove(managedentity);     return !entitymanager.contains(managedentity); } 

the entity supplied client associated detached entity. entitymanager.remove() operation produces delete dml statement following,

delete db.entity ((id = ?) , (version = ?)) 

the additional check and (version = ?) should cause javax.persistence.optimisticlockexception thrown, if row version in database conflicts row version in entity.

this nevertheless not throw javax.persistence.optimisticlockexception though supplied entity modified concurrently in session user, since last read client (web or otherwise) because find() method obtains entity updated row version in transaction (the old/stale row version (as marked @javax.persistence.version) contained detached entity supplied method argument).

unlike entitymanager#merge(t entity), entitymanager#remove(object entity) not accept detached entity. error passing detached entity remove().

java.lang.illegalargumentexception: entity must managed call remove: com.example.entity[ id=1 ], try merging detached , try remove again. 

merging entity directly before removing like,

entitymanager.remove(entitymanager.contains(entity) ? entity : entitymanager.merge(entity)); 

causes other issues, if entity has associations.

it leaves 1 alternative optimistic locking check row version manually , make javax.persistence.optimisticlockexception thrown manually not approach 1 may expect.

long story short : how make javax.persistence.optimisticlockexception thrown while deleting entity(ies), if entity deleted modified behind session? approach mentioned above not work optimistic locking.

if want avoid classing merge, can 'soft merge' instead - take version detached instance , set managed one:

entity managedentity = entitymanager.find(entity.class, entity.getid()); if (managedentity == null) {     throw new entitynotfoundexception(); } managedentity.setversion(entity.getversion()); 

of course, not repeat yourself, depending on hierarchy of daos, repositories etc, can make generic softmerge method load managed entity, take version detached instance , set managed one.


Comments