/**
   * Handle the given lock event.
   *
   * @param event The lock event to be handled.
   * @throws HibernateException
   */
  public void onLock(LockEvent event) throws HibernateException {

    if (event.getObject() == null) {
      throw new NullPointerException("attempted to lock null");
    }

    if (event.getLockMode() == LockMode.WRITE) {
      throw new HibernateException("Invalid lock mode for lock()");
    }

    SessionImplementor source = event.getSession();

    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.getEntityMode());
      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.getLockMode(), source);
  }
 private void cascadeOnLock(LockEvent event, EntityPersister persister, Object entity) {
   EventSource source = event.getSession();
   source.getPersistenceContext().incrementCascadeLevel();
   try {
     new Cascade(CascadingAction.LOCK, Cascade.AFTER_LOCK, source)
         .cascade(persister, entity, event.getLockMode());
   } finally {
     source.getPersistenceContext().decrementCascadeLevel();
   }
 }