[hibernate-dev] DefaultLockEventListener cascading

Mihalcea Vlad mih_vlad at yahoo.com
Mon Mar 9 18:13:26 EDT 2015


Hi,
While investigating how Lock Cascading works, I realized that the lock "scope" is only applied for detached entities.
Object entity = source.getPersistenceContext().unproxyAndReassociate( event.getObject() );
//TODO: if object was an uninitialized proxy, this is inefficient,
//      resulting in two SQL selects

EntityEntry entry = source.getPersistenceContext().getEntry(entity);
if (entry==null) {
   final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
   final Serializable id = persister.getIdentifier( entity, source );
   if ( !ForeignKeys.isNotTransient( event.getEntityName(), entity, Boolean.FALSE, source ) ) {
      throw new TransientObjectException(
            "cannot lock an unsaved transient instance: " +
            persister.getEntityName()
      );
   }

   entry = reassociate(event, entity, id, persister);
   cascadeOnLock(event, persister, entity);
}

upgradeLock( entity, entry, event.getLockOptions(), event.getSession() );

If an entity is already attached, the Lock will only be applied to the request entity.
If the lock request entity is detached, then it will be:
- re-associated
- and the lock cascade will be propagated
The Cascade lock action looks like this:
LockMode lockMode = LockMode.NONE;
LockOptions lr = new LockOptions();
if ( anything instanceof LockOptions ) {
   LockOptions lockOptions = (LockOptions) anything;
   lr.setTimeOut( lockOptions.getTimeOut() );
   lr.setScope( lockOptions.getScope() );
   if ( lockOptions.getScope() ) {
      lockMode = lockOptions.getLockMode();
   }
}
lr.setLockMode( lockMode );
session.buildLockRequest( lr ).lock( entityName, child );So, if I specify a "scope" lock request I can propagate the lock to all child association (configured with CascadeType.ALL or CascadeType.LOCK):
Query:{[select id from Comment where id =? for update][1]} 
Query:{[select id from Comment where id =? for update][2]} 
Query:{[select id from PostDetails where id =? for update][1]}
Query:{[select id from Post where id =? for update][1]} 
Shouldn't this logic be consistent for both attached and detached entities?
The test is available on GitHub:
https://github.com/vladmihalcea/hibernate-master-class/blob/master/core/src/test/java/com/vladmihalcea/hibernate/masterclass/laboratory/concurrency/CascadeLockTest.java

Vlad Mihalcea


More information about the hibernate-dev mailing list