[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