Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/hibernate/dialect/lock/UpdateLockingStrategy.java


1   package org.hibernate.dialect.lock;
2   
3   import org.hibernate.persister.entity.Lockable;
4   import org.hibernate.LockMode;
5   import org.hibernate.HibernateException;
6   import org.hibernate.StaleObjectStateException;
7   import org.hibernate.JDBCException;
8   import org.hibernate.pretty.MessageHelper;
9   import org.hibernate.exception.JDBCExceptionHelper;
10  import org.hibernate.sql.Update;
11  import org.hibernate.engine.SessionImplementor;
12  import org.hibernate.engine.SessionFactoryImplementor;
13  import org.apache.commons.logging.Log;
14  import org.apache.commons.logging.LogFactory;
15  
16  import java.io.Serializable;
17  import java.sql.PreparedStatement;
18  import java.sql.SQLException;
19  
20  /**
21   * A locking strategy where the locks are obtained through update statements.
22   * <p/>
23   * This strategy is not valid for read style locks.
24   *
25   * @since 3.2
26   *
27   * @author Steve Ebersole
28   */
29  public class UpdateLockingStrategy implements LockingStrategy {
30    private static final Log log = LogFactory.getLog( UpdateLockingStrategy.class );
31  
32    private final Lockable lockable;
33    private final LockMode lockMode;
34    private final String sql;
35  
36    /**
37     * Construct a locking strategy based on SQL UPDATE statements.
38     *
39     * @param lockable The metadata for the entity to be locked.
40     * @param lockMode Indictates the type of lock to be acquired.  Note that
41     * read-locks are not valid for this strategy.
42     */
43    public UpdateLockingStrategy(Lockable lockable, LockMode lockMode) {
44      this.lockable = lockable;
45      this.lockMode = lockMode;
46      if ( lockMode.lessThan( LockMode.UPGRADE ) ) {
47        throw new HibernateException( "[" + lockMode + "] not valid for update statement" );
48      }
49      if ( !lockable.isVersioned() ) {
50        log.warn( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
51        this.sql = null;
52      }
53      else {
54        this.sql = generateLockString();
55      }
56    }
57  
58    /**
59     * @see LockingStrategy#lock
60     */
61    public void lock(
62        Serializable id,
63            Object version,
64            Object object,
65            SessionImplementor session) throws StaleObjectStateException, JDBCException {
66      if ( !lockable.isVersioned() ) {
67        throw new HibernateException( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
68      }
69      // todo : should we additionally check the current isolation mode explicitly?
70      SessionFactoryImplementor factory = session.getFactory();
71      try {
72        PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
73        try {
74          lockable.getVersionType().nullSafeSet( st, version, 1, session );
75          int offset = 2;
76  
77          lockable.getIdentifierType().nullSafeSet( st, id, offset, session );
78          offset += lockable.getIdentifierType().getColumnSpan( factory );
79  
80          if ( lockable.isVersioned() ) {
81            lockable.getVersionType().nullSafeSet( st, version, offset, session );
82          }
83  
84          int affected = st.executeUpdate();
85          if ( affected < 0 ) {
86            factory.getStatisticsImplementor().optimisticFailure( lockable.getEntityName() );
87            throw new StaleObjectStateException( lockable.getEntityName(), id );
88          }
89  
90        }
91        finally {
92          session.getBatcher().closeStatement( st );
93        }
94  
95      }
96      catch ( SQLException sqle ) {
97        throw JDBCExceptionHelper.convert(
98            session.getFactory().getSQLExceptionConverter(),
99                sqle,
100               "could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
101               sql
102       );
103     }
104   }
105 
106   protected String generateLockString() {
107     SessionFactoryImplementor factory = lockable.getFactory();
108     Update update = new Update( factory.getDialect() );
109     update.setTableName( lockable.getRootTableName() );
110     update.setPrimaryKeyColumnNames( lockable.getRootTableIdentifierColumnNames() );
111     update.setVersionColumnName( lockable.getVersionColumnName() );
112     update.addColumn( lockable.getVersionColumnName() );
113     if ( factory.getSettings().isCommentsEnabled() ) {
114       update.setComment( lockMode + " lock " + lockable.getEntityName() );
115     }
116     return update.toStatementString();
117   }
118 
119   protected LockMode getLockMode() {
120     return lockMode;
121   }
122 }