001: //$Id: AbstractLockUpgradeEventListener.java 9328 2006-02-23 17:32:47Z steveebersole $
002: package org.hibernate.event.def;
003:
004: import org.apache.commons.logging.Log;
005: import org.apache.commons.logging.LogFactory;
006:
007: import org.hibernate.HibernateException;
008: import org.hibernate.LockMode;
009: import org.hibernate.ObjectDeletedException;
010: import org.hibernate.cache.CacheConcurrencyStrategy;
011: import org.hibernate.cache.CacheKey;
012: import org.hibernate.engine.EntityEntry;
013: import org.hibernate.engine.Status;
014: import org.hibernate.engine.SessionImplementor;
015: import org.hibernate.persister.entity.EntityPersister;
016: import org.hibernate.pretty.MessageHelper;
017:
018: /**
019: * A convenience base class for listeners that respond to requests to perform a
020: * pessimistic lock upgrade on an entity.
021: *
022: * @author Gavin King
023: */
024: public class AbstractLockUpgradeEventListener extends
025: AbstractReassociateEventListener {
026:
027: private static final Log log = LogFactory
028: .getLog(AbstractLockUpgradeEventListener.class);
029:
030: /**
031: * Performs a pessimistic lock upgrade on a given entity, if needed.
032: *
033: * @param object The entity for which to upgrade the lock.
034: * @param entry The entity's EntityEntry instance.
035: * @param requestedLockMode The lock mode being requested for locking.
036: * @param source The session which is the source of the event being processed.
037: * @throws HibernateException
038: */
039: protected void upgradeLock(Object object, EntityEntry entry,
040: LockMode requestedLockMode, SessionImplementor source)
041: throws HibernateException {
042:
043: if (requestedLockMode.greaterThan(entry.getLockMode())) {
044: // The user requested a "greater" (i.e. more restrictive) form of
045: // pessimistic lock
046:
047: if (entry.getStatus() != Status.MANAGED) {
048: throw new ObjectDeletedException(
049: "attempted to lock a deleted instance", entry
050: .getId(), entry.getPersister()
051: .getEntityName());
052: }
053:
054: final EntityPersister persister = entry.getPersister();
055:
056: if (log.isTraceEnabled())
057: log.trace("locking "
058: + MessageHelper.infoString(persister, entry
059: .getId(), source.getFactory())
060: + " in mode: " + requestedLockMode);
061:
062: final CacheConcurrencyStrategy.SoftLock lock;
063: final CacheKey ck;
064: if (persister.hasCache()) {
065: ck = new CacheKey(entry.getId(), persister
066: .getIdentifierType(), persister
067: .getRootEntityName(), source.getEntityMode(),
068: source.getFactory());
069: lock = persister.getCache()
070: .lock(ck, entry.getVersion());
071: } else {
072: ck = null;
073: lock = null;
074: }
075:
076: try {
077: if (persister.isVersioned()
078: && requestedLockMode == LockMode.FORCE) {
079: // todo : should we check the current isolation mode explicitly?
080: Object nextVersion = persister
081: .forceVersionIncrement(entry.getId(), entry
082: .getVersion(), source);
083: entry.forceLocked(object, nextVersion);
084: } else {
085: persister.lock(entry.getId(), entry.getVersion(),
086: object, requestedLockMode, source);
087: }
088: entry.setLockMode(requestedLockMode);
089: } finally {
090: // the database now holds a lock + the object is flushed from the cache,
091: // so release the soft lock
092: if (persister.hasCache()) {
093: persister.getCache().release(ck, lock);
094: }
095: }
096:
097: }
098: }
099:
100: }
|