[hibernate-commits] Hibernate SVN: r17962 - in core/trunk/core/src/main/java/org/hibernate: dialect and 3 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Nov 11 23:20:41 EST 2009


Author: smarlow at redhat.com
Date: 2009-11-11 23:20:41 -0500 (Wed, 11 Nov 2009)
New Revision: 17962

Added:
   core/trunk/core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java
   core/trunk/core/src/main/java/org/hibernate/dialect/lock/OptimisticLockingStrategy.java
   core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticForceIncrementLockingStrategy.java
   core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java
   core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java
   core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java
   core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java
Modified:
   core/trunk/core/src/main/java/org/hibernate/LockMode.java
   core/trunk/core/src/main/java/org/hibernate/dialect/Cache71Dialect.java
   core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java
   core/trunk/core/src/main/java/org/hibernate/dialect/FrontBaseDialect.java
   core/trunk/core/src/main/java/org/hibernate/dialect/HSQLDialect.java
   core/trunk/core/src/main/java/org/hibernate/dialect/MckoiDialect.java
   core/trunk/core/src/main/java/org/hibernate/dialect/PointbaseDialect.java
   core/trunk/core/src/main/java/org/hibernate/dialect/RDMSOS2200Dialect.java
   core/trunk/core/src/main/java/org/hibernate/dialect/SQLServerDialect.java
   core/trunk/core/src/main/java/org/hibernate/dialect/TimesTenDialect.java
   core/trunk/core/src/main/java/org/hibernate/dialect/lock/LockingStrategy.java
   core/trunk/core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java
   core/trunk/core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java
   core/trunk/core/src/main/java/org/hibernate/event/def/AbstractLockUpgradeEventListener.java
   core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
Log:
HHH-4546 - add JPA 2.0 locking.

Modified: core/trunk/core/src/main/java/org/hibernate/LockMode.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/LockMode.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/LockMode.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -120,30 +120,30 @@
 	 * Optimisticly assume that transaction will not experience contention for
 	 * entities.  The entity version will be verified near the transaction end.  
 	 */
-	public static final LockMode OPTIMISTIC = new LockMode(3,"OPTIMISTIC");
+	public static final LockMode OPTIMISTIC = new LockMode( 3, "OPTIMISTIC");
 
 	/**
 	 * Optimisticly assume that transaction will not experience contention for entities.
 	 * The entity version will be verified and incremented near the transaction end. 
 	 */
-	public static final LockMode OPTIMISTIC_FORCE_INCREMENT = new LockMode(7,"OPTIMISTIC_FORCE_INCREMENT");
+	public static final LockMode OPTIMISTIC_FORCE_INCREMENT = new LockMode( 4, "OPTIMISTIC_FORCE_INCREMENT");
 
 	/**
 	 * Implemented as PESSIMISTIC_WRITE.
 	 * TODO:  introduce separate support for PESSIMISTIC_READ
 	 */
-	public static final LockMode PESSIMISTIC_READ = new LockMode(12,"PESSIMISTIC_READ");
+	public static final LockMode PESSIMISTIC_READ = new LockMode( 12, "PESSIMISTIC_READ");
 
 	/**
 	 * Transaction will obtain a database lock immediately.
 	 * TODO:  add PESSIMISTIC_WRITE_NOWAIT
 	 */
-	public static final LockMode PESSIMISTIC_WRITE = new LockMode(13,"PESSIMISTIC_WRITE");
+	public static final LockMode PESSIMISTIC_WRITE = new LockMode( 13, "PESSIMISTIC_WRITE");
 
 	/**
 	 * Transaction will immediately increment the entity version.
 	 */
-	public static final LockMode PESSIMISTIC_FORCE_INCREMENT = new LockMode(17,"PESSIMISTIC_FORCE_INCREMENT");
+	public static final LockMode PESSIMISTIC_FORCE_INCREMENT = new LockMode( 17, "PESSIMISTIC_FORCE_INCREMENT");
 
 	/**
 	 *  end of javax.persistence.LockModeType modes

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/Cache71Dialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/Cache71Dialect.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/Cache71Dialect.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -41,9 +41,7 @@
 import org.hibernate.dialect.function.StandardJDBCEscapeFunction;
 import org.hibernate.dialect.function.ConvertFunction;
 import org.hibernate.dialect.function.ConditionalParenthesisFunction;
-import org.hibernate.dialect.lock.LockingStrategy;
-import org.hibernate.dialect.lock.SelectLockingStrategy;
-import org.hibernate.dialect.lock.UpdateLockingStrategy;
+import org.hibernate.dialect.lock.*;
 import org.hibernate.exception.CacheSQLStateConverter;
 import org.hibernate.exception.SQLExceptionConverter;
 import org.hibernate.exception.TemplatedViolatedConstraintNameExtracter;
@@ -564,7 +562,22 @@
 	public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
 		// InterSystems Cache' does not current support "SELECT ... FOR UPDATE" syntax...
 		// Set your transaction mode to READ_COMMITTED before using
-		if ( lockMode.greaterThan( LockMode.READ ) ) {
+		if ( lockMode==LockMode.PESSIMISTIC_FORCE_INCREMENT) {
+			return new PessimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_WRITE) {
+			return new PessimisticWriteUpdateLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_READ) {
+			return new PessimisticReadUpdateLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC) {
+			return new OptimisticLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC_FORCE_INCREMENT) {
+			return new OptimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode.greaterThan( LockMode.READ ) ) {
 			return new UpdateLockingStrategy( lockable, lockMode );
 		}
 		else {

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/Dialect.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -48,8 +48,7 @@
 import org.hibernate.dialect.function.SQLFunction;
 import org.hibernate.dialect.function.SQLFunctionTemplate;
 import org.hibernate.dialect.function.StandardSQLFunction;
-import org.hibernate.dialect.lock.LockingStrategy;
-import org.hibernate.dialect.lock.SelectLockingStrategy;
+import org.hibernate.dialect.lock.*;
 import org.hibernate.engine.Mapping;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.exception.SQLExceptionConverter;
@@ -952,6 +951,21 @@
 	 * @since 3.2
 	 */
 	public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
+		if ( lockMode==LockMode.PESSIMISTIC_FORCE_INCREMENT) {
+			return new PessimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_WRITE) {
+			return new PessimisticWriteSelectLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_READ) {
+			return new PessimisticReadSelectLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC) {
+			return new OptimisticLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC_FORCE_INCREMENT) {
+			return new OptimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
 		return new SelectLockingStrategy( lockable, lockMode );
 	}
 

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/FrontBaseDialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/FrontBaseDialect.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/FrontBaseDialect.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -24,9 +24,7 @@
  */
 package org.hibernate.dialect;
 
-import org.hibernate.dialect.lock.LockingStrategy;
-import org.hibernate.dialect.lock.UpdateLockingStrategy;
-import org.hibernate.dialect.lock.SelectLockingStrategy;
+import org.hibernate.dialect.lock.*;
 import org.hibernate.persister.entity.Lockable;
 import org.hibernate.LockMode;
 
@@ -104,7 +102,22 @@
 
 	public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
 		// Frontbase has no known variation of a "SELECT ... FOR UPDATE" syntax...
-		if ( lockMode.greaterThan( LockMode.READ ) ) {
+		if ( lockMode==LockMode.PESSIMISTIC_FORCE_INCREMENT) {
+			return new PessimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_WRITE) {
+			return new PessimisticWriteUpdateLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_READ) {
+			return new PessimisticReadUpdateLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC) {
+			return new OptimisticLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC_FORCE_INCREMENT) {
+			return new OptimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode.greaterThan( LockMode.READ ) ) {
 			return new UpdateLockingStrategy( lockable, lockMode );
 		}
 		else {

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/HSQLDialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/HSQLDialect.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/HSQLDialect.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -38,8 +38,7 @@
 import org.hibernate.dialect.function.NoArgSQLFunction;
 import org.hibernate.dialect.function.StandardSQLFunction;
 import org.hibernate.dialect.function.VarArgsSQLFunction;
-import org.hibernate.dialect.lock.LockingStrategy;
-import org.hibernate.dialect.lock.SelectLockingStrategy;
+import org.hibernate.dialect.lock.*;
 import org.hibernate.exception.JDBCExceptionHelper;
 import org.hibernate.exception.TemplatedViolatedConstraintNameExtracter;
 import org.hibernate.exception.ViolatedConstraintNameExtracter;
@@ -292,7 +291,17 @@
 
 	public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
 		// HSQLDB only supports READ_UNCOMMITTED transaction isolation
+		if ( lockMode==LockMode.PESSIMISTIC_FORCE_INCREMENT) {
+			return new PessimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC) {
+			return new OptimisticLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC_FORCE_INCREMENT) {
+			return new OptimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
 		return new ReadUncommittedLockingStrategy( lockable, lockMode );
+		
 	}
 
 	public static class ReadUncommittedLockingStrategy extends SelectLockingStrategy {
@@ -300,12 +309,12 @@
 			super( lockable, lockMode );
 		}
 
-		public void lock(Serializable id, Object version, Object object, SessionImplementor session)
+		public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session)
 				throws StaleObjectStateException, JDBCException {
 			if ( getLockMode().greaterThan( LockMode.READ ) ) {
 				log.warn( "HSQLDB supports only READ_UNCOMMITTED isolation" );
 			}
-			super.lock( id, version, object, session );
+			super.lock( id, version, object, timeout, session );
 		}
 	}
 

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/MckoiDialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/MckoiDialect.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/MckoiDialect.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -31,9 +31,7 @@
 import org.hibernate.persister.entity.Lockable;
 import org.hibernate.cfg.Environment;
 import org.hibernate.dialect.function.StandardSQLFunction;
-import org.hibernate.dialect.lock.LockingStrategy;
-import org.hibernate.dialect.lock.UpdateLockingStrategy;
-import org.hibernate.dialect.lock.SelectLockingStrategy;
+import org.hibernate.dialect.lock.*;
 import org.hibernate.sql.CaseFragment;
 import org.hibernate.sql.MckoiCaseFragment;
 
@@ -111,7 +109,22 @@
 
 	public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
 		// Mckoi has no known variation of a "SELECT ... FOR UPDATE" syntax...
-		if ( lockMode.greaterThan( LockMode.READ ) ) {
+		if ( lockMode==LockMode.PESSIMISTIC_FORCE_INCREMENT) {
+			return new PessimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_WRITE) {
+			return new PessimisticWriteUpdateLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_READ) {
+			return new PessimisticReadUpdateLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC) {
+			return new OptimisticLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC_FORCE_INCREMENT) {
+			return new OptimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode.greaterThan( LockMode.READ ) ) {
 			return new UpdateLockingStrategy( lockable, lockMode );
 		}
 		else {

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/PointbaseDialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/PointbaseDialect.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/PointbaseDialect.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -24,9 +24,7 @@
  */
 package org.hibernate.dialect;
 
-import org.hibernate.dialect.lock.LockingStrategy;
-import org.hibernate.dialect.lock.UpdateLockingStrategy;
-import org.hibernate.dialect.lock.SelectLockingStrategy;
+import org.hibernate.dialect.lock.*;
 import org.hibernate.persister.entity.Lockable;
 import org.hibernate.LockMode;
 
@@ -81,7 +79,22 @@
 
 	public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
 		// Pointbase has no known variation of a "SELECT ... FOR UPDATE" syntax...
-		if ( lockMode.greaterThan( LockMode.READ ) ) {
+		if ( lockMode==LockMode.PESSIMISTIC_FORCE_INCREMENT) {
+			return new PessimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_WRITE) {
+			return new PessimisticWriteUpdateLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_READ) {
+			return new PessimisticReadUpdateLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC) {
+			return new OptimisticLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC_FORCE_INCREMENT) {
+			return new OptimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode.greaterThan( LockMode.READ ) ) {
 			return new UpdateLockingStrategy( lockable, lockMode );
 		}
 		else {

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/RDMSOS2200Dialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/RDMSOS2200Dialect.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/RDMSOS2200Dialect.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -27,9 +27,7 @@
 import org.hibernate.dialect.function.NoArgSQLFunction;
 import org.hibernate.dialect.function.StandardSQLFunction;
 import org.hibernate.dialect.function.SQLFunctionTemplate;
-import org.hibernate.dialect.lock.LockingStrategy;
-import org.hibernate.dialect.lock.UpdateLockingStrategy;
-import org.hibernate.dialect.lock.SelectLockingStrategy;
+import org.hibernate.dialect.lock.*;
 
 import java.sql.Types;
 import org.hibernate.Hibernate;
@@ -336,7 +334,22 @@
 
 	public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
 		// RDMS has no known variation of a "SELECT ... FOR UPDATE" syntax...
-		if ( lockMode.greaterThan( LockMode.READ ) ) {
+		if ( lockMode==LockMode.PESSIMISTIC_FORCE_INCREMENT) {
+			return new PessimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_WRITE) {
+			return new PessimisticWriteUpdateLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_READ) {
+			return new PessimisticReadUpdateLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC) {
+			return new OptimisticLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC_FORCE_INCREMENT) {
+			return new OptimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode.greaterThan( LockMode.READ ) ) {
 			return new UpdateLockingStrategy( lockable, lockMode );
 		}
 		else {

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/SQLServerDialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/SQLServerDialect.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/SQLServerDialect.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -111,10 +111,15 @@
 	}
 
 	public String appendLockHint(LockMode mode, String tableName) {
-		if ( mode.greaterThan( LockMode.READ ) ) {
-			// does this need holdlock also? : return tableName + " with (updlock, rowlock, holdlock)";
+		if ( ( mode == LockMode.UPGRADE ) ||
+			  ( mode == LockMode.UPGRADE_NOWAIT ) ||
+			  ( mode == LockMode.PESSIMISTIC_WRITE ) ||			
+			  ( mode == LockMode.WRITE ) ) {
 			return tableName + " with (updlock, rowlock)";
 		}
+		else if ( mode == LockMode.PESSIMISTIC_READ ) {
+			return tableName + " with (holdlock, rowlock)";
+		}
 		else {
 			return tableName;
 		}

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/TimesTenDialect.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/TimesTenDialect.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/TimesTenDialect.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -32,9 +32,7 @@
 import org.hibernate.cfg.Environment;
 import org.hibernate.dialect.function.NoArgSQLFunction;
 import org.hibernate.dialect.function.StandardSQLFunction;
-import org.hibernate.dialect.lock.LockingStrategy;
-import org.hibernate.dialect.lock.UpdateLockingStrategy;
-import org.hibernate.dialect.lock.SelectLockingStrategy;
+import org.hibernate.dialect.lock.*;
 import org.hibernate.sql.JoinFragment;
 import org.hibernate.sql.OracleJoinFragment;
 
@@ -217,7 +215,22 @@
 
 	public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
 		// TimesTen has no known variation of a "SELECT ... FOR UPDATE" syntax...
-		if ( lockMode.greaterThan( LockMode.READ ) ) {
+		if ( lockMode==LockMode.PESSIMISTIC_FORCE_INCREMENT) {
+			return new PessimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_WRITE) {
+			return new PessimisticWriteUpdateLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.PESSIMISTIC_READ) {
+			return new PessimisticReadUpdateLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC) {
+			return new OptimisticLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode==LockMode.OPTIMISTIC_FORCE_INCREMENT) {
+			return new OptimisticForceIncrementLockingStrategy( lockable, lockMode);
+		}
+		else if ( lockMode.greaterThan( LockMode.READ ) ) {
 			return new UpdateLockingStrategy( lockable, lockMode );
 		}
 		else {

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/lock/LockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/LockingStrategy.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/LockingStrategy.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -51,11 +51,12 @@
 	 * @param id The id of the row to be locked
 	 * @param version The current version (or null if not versioned)
 	 * @param object The object logically being locked (currently not used)
+	 * @param timeout timeout in milliseconds, 0 = no wait, -1 = wait indefinitely
 	 * @param session The session from which the lock request originated
 	 * @throws StaleObjectStateException Indicates an optimisitic lock failure
 	 * as part of acquiring the requested database lock.
 	 * @throws JDBCException
 	 */
-	public void lock(Serializable id, Object version, Object object, SessionImplementor session)
+	public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session)
 	throws StaleObjectStateException, JDBCException;
 }

Added: core/trunk/core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/OptimisticForceIncrementLockingStrategy.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -0,0 +1,91 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.dialect.lock;
+
+import java.io.Serializable;
+
+import org.hibernate.HibernateException;
+import org.hibernate.JDBCException;
+import org.hibernate.LockMode;
+import org.hibernate.StaleObjectStateException;
+import org.hibernate.event.EventSource;
+import org.hibernate.action.EntityIncrementVersionProcess;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.EntityEntry;
+import org.hibernate.persister.entity.Lockable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An optimistic locking strategy that forces an increment of the version (after verifying that version hasn't changed).
+ * This takes place just prior to transaction commit.
+ * <p/>
+ * This strategy is valid for LockMode.OPTIMISTIC_FORCE_INCREMENT
+ *
+ * @since 3.5
+ *
+ * @author Scott Marlow
+ */
+public class OptimisticForceIncrementLockingStrategy implements LockingStrategy {
+	private static final Logger log = LoggerFactory.getLogger( OptimisticForceIncrementLockingStrategy.class );
+
+	private final Lockable lockable;
+	private final LockMode lockMode;
+                                             	/**
+	 * Construct locking strategy.
+	 *
+	 * @param lockable The metadata for the entity to be locked.
+	 * @param lockMode Indictates the type of lock to be acquired.
+	 */
+	public OptimisticForceIncrementLockingStrategy(Lockable lockable, LockMode lockMode) {
+		this.lockable = lockable;
+		this.lockMode = lockMode;
+		if ( lockMode.lessThan( LockMode.OPTIMISTIC_FORCE_INCREMENT ) ) {
+			throw new HibernateException( "[" + lockMode + "] not valid for [" + lockable.getEntityName() + "]" );
+		}
+	}
+
+   /**
+	 * @see LockingStrategy#lock
+	 */
+	public void lock(
+      Serializable id,
+      Object version,
+      Object object,
+      int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
+		if ( !lockable.isVersioned() ) {
+			throw new HibernateException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
+		}
+      EntityEntry entry = session.getPersistenceContext().getEntry(object);
+		EntityIncrementVersionProcess incrementVersion = new EntityIncrementVersionProcess(object, entry);
+		EventSource source = (EventSource)session;
+		// Register the EntityIncrementVersionProcess action to run just prior to transaction commit. 
+		source.getActionQueue().registerProcess(incrementVersion);
+	}
+
+	protected LockMode getLockMode() {
+		return lockMode;
+	}
+}
\ No newline at end of file

Added: core/trunk/core/src/main/java/org/hibernate/dialect/lock/OptimisticLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/OptimisticLockingStrategy.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/OptimisticLockingStrategy.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -0,0 +1,88 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.dialect.lock;
+
+import java.io.Serializable;
+
+import org.hibernate.*;
+import org.hibernate.event.EventSource;
+import org.hibernate.action.EntityVerifyVersionProcess;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.EntityEntry;
+import org.hibernate.persister.entity.Lockable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An optimistic locking strategy that verifies that the version hasn't changed (prior to transaction commit).
+ * <p/>
+ * This strategy is valid for LockMode.OPTIMISTIC
+ *
+ * @since 3.5
+ *
+ * @author Scott Marlow
+ */
+public class OptimisticLockingStrategy implements LockingStrategy {
+	private static final Logger log = LoggerFactory.getLogger( OptimisticLockingStrategy.class );
+
+	private final Lockable lockable;
+	private final LockMode lockMode;
+
+	/**
+	 * Construct locking strategy.
+	 *
+	 * @param lockable The metadata for the entity to be locked.
+	 * @param lockMode Indictates the type of lock to be acquired.
+	 */
+	public OptimisticLockingStrategy(Lockable lockable, LockMode lockMode) {
+		this.lockable = lockable;
+		this.lockMode = lockMode;
+		if ( lockMode.lessThan( LockMode.OPTIMISTIC ) ) {
+			throw new HibernateException( "[" + lockMode + "] not valid for [" + lockable.getEntityName() + "]" );
+		}
+	}
+
+   /**
+	 * @see org.hibernate.dialect.lock.LockingStrategy#lock
+	 */
+	public void lock(
+      Serializable id,
+      Object version,
+      Object object,
+      int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
+		if ( !lockable.isVersioned() ) {
+			throw new OptimisticLockException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
+		}
+		EntityEntry entry = session.getPersistenceContext().getEntry(object);
+		EventSource source = (EventSource)session;
+		EntityVerifyVersionProcess verifyVersion = new EntityVerifyVersionProcess(object, entry);
+		// Register the EntityVerifyVersionProcess action to run just prior to transaction commit.
+		source.getActionQueue().registerProcess(verifyVersion);
+	}
+
+	protected LockMode getLockMode() {
+		return lockMode;
+	}
+}
\ No newline at end of file

Added: core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticForceIncrementLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticForceIncrementLockingStrategy.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticForceIncrementLockingStrategy.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -0,0 +1,93 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.dialect.lock;
+
+import java.io.Serializable;
+
+import org.hibernate.HibernateException;
+import org.hibernate.JDBCException;
+import org.hibernate.LockMode;
+import org.hibernate.StaleObjectStateException;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.EntityEntry;
+import org.hibernate.persister.entity.Lockable;
+import org.hibernate.persister.entity.EntityPersister;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A pessimistic locking strategy that increments the version immediately (obtaining an exclusive write lock).
+ * <p/>
+ * This strategy is valid for LockMode.PESSIMISTIC_FORCE_INCREMENT
+ *
+ * @since 3.5
+ *
+ * @author Scott Marlow
+ */
+public class PessimisticForceIncrementLockingStrategy implements LockingStrategy {
+	private static final Logger log = LoggerFactory.getLogger( PessimisticForceIncrementLockingStrategy.class );
+
+	private final Lockable lockable;
+	private final LockMode lockMode;
+
+	/**
+	 * Construct locking strategy.
+	 *
+	 * @param lockable The metadata for the entity to be locked.
+	 * @param lockMode Indictates the type of lock to be acquired.
+	 */
+	public PessimisticForceIncrementLockingStrategy(Lockable lockable, LockMode lockMode) {
+		this.lockable = lockable;
+		this.lockMode = lockMode;
+		// ForceIncrement can be used for PESSIMISTIC_READ, PESSIMISTIC_WRITE or PESSIMISTIC_FORCE_INCREMENT
+		if ( lockMode.lessThan( LockMode.PESSIMISTIC_READ ) ) {
+			throw new HibernateException( "[" + lockMode + "] not valid for [" + lockable.getEntityName() + "]" );
+		}
+	}
+
+   /**
+	 * @see org.hibernate.dialect.lock.LockingStrategy#lock
+	 */
+	public void lock(
+      Serializable id,
+      Object version,
+      Object object,
+      int timeout,
+		SessionImplementor session) throws StaleObjectStateException, JDBCException {
+		if ( !lockable.isVersioned() ) {
+			throw new HibernateException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
+		}
+      EntityEntry entry = session.getPersistenceContext().getEntry(object);
+      final EntityPersister persister = entry.getPersister();
+      Object nextVersion = persister.forceVersionIncrement(
+            entry.getId(), entry.getVersion(), session
+      );
+      entry.forceLocked( object, nextVersion );
+	}
+
+	protected LockMode getLockMode() {
+		return lockMode;
+	}
+}
\ No newline at end of file

Added: core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticReadSelectLockingStrategy.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -0,0 +1,148 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.dialect.lock;
+
+import org.hibernate.persister.entity.Lockable;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.StaleObjectStateException;
+import org.hibernate.JDBCException;
+import org.hibernate.LockMode;
+import org.hibernate.sql.SimpleSelect;
+import org.hibernate.pretty.MessageHelper;
+import org.hibernate.exception.JDBCExceptionHelper;
+
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * A pessimistic locking strategy where the locks are obtained through select statements.
+ * <p/>
+ * For non-read locks, this is achieved through the Dialect's specific
+ * SELECT ... FOR UPDATE syntax.
+ *
+ * This strategy is valid for LockMode.PESSIMISTIC_READ
+ *
+ * This class is a clone of SelectLockingStrategy.
+ *
+ * @see org.hibernate.dialect.Dialect#getForUpdateString(org.hibernate.LockMode)
+ * @see org.hibernate.dialect.Dialect#appendLockHint(org.hibernate.LockMode, String)
+ * @since 3.5
+ *
+ * @author Steve Ebersole
+ * @author Scott Marlow
+ */
+public class PessimisticReadSelectLockingStrategy implements LockingStrategy {
+
+	private final Lockable lockable;
+	private final LockMode lockMode;
+	private final String sql;
+
+	/**
+	 * Construct a locking strategy based on SQL SELECT statements.
+	 *
+	 * @param lockable The metadata for the entity to be locked.
+	 * @param lockMode Indictates the type of lock to be acquired.
+	 */
+	public PessimisticReadSelectLockingStrategy(Lockable lockable, LockMode lockMode) {
+		this.lockable = lockable;
+		this.lockMode = lockMode;
+		this.sql = generateLockString();
+	}
+
+   /**
+	 * @see org.hibernate.dialect.lock.LockingStrategy#lock
+	 */
+	public void lock(
+      Serializable id,
+      Object version,
+      Object object,
+      int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
+
+		SessionFactoryImplementor factory = session.getFactory();
+		try {
+			PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
+			try {
+				lockable.getIdentifierType().nullSafeSet( st, id, 1, session );
+				if ( lockable.isVersioned() ) {
+					lockable.getVersionType().nullSafeSet(
+							st,
+							version,
+							lockable.getIdentifierType().getColumnSpan( factory ) + 1,
+							session
+					);
+				}
+
+				ResultSet rs = st.executeQuery();
+				try {
+					if ( !rs.next() ) {
+						if ( factory.getStatistics().isStatisticsEnabled() ) {
+							factory.getStatisticsImplementor()
+									.optimisticFailure( lockable.getEntityName() );
+						}
+						throw new StaleObjectStateException( lockable.getEntityName(), id );
+					}
+				}
+				finally {
+					rs.close();
+				}
+			}
+			finally {
+				session.getBatcher().closeStatement( st );
+			}
+
+		}
+		catch ( SQLException sqle ) {
+			throw JDBCExceptionHelper.convert(
+					session.getFactory().getSQLExceptionConverter(),
+					sqle,
+					"could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
+					sql
+				);
+		}
+	}
+
+	protected LockMode getLockMode() {
+		return lockMode;
+	}
+
+	protected String generateLockString() {
+		SessionFactoryImplementor factory = lockable.getFactory();
+		SimpleSelect select = new SimpleSelect( factory.getDialect() )
+				.setLockMode( lockMode )
+				.setTableName( lockable.getRootTableName() )
+				.addColumn( lockable.getRootTableIdentifierColumnNames()[0] )
+				.addCondition( lockable.getRootTableIdentifierColumnNames(), "=?" );
+		if ( lockable.isVersioned() ) {
+			select.addCondition( lockable.getVersionColumnName(), "=?" );
+		}
+		if ( factory.getSettings().isCommentsEnabled() ) {
+			select.setComment( lockMode + " lock " + lockable.getEntityName() );
+		}
+		return select.toStatementString();
+	}
+}
\ No newline at end of file

Added: core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticReadUpdateLockingStrategy.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -0,0 +1,148 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.dialect.lock;
+
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+import org.hibernate.HibernateException;
+import org.hibernate.JDBCException;
+import org.hibernate.LockMode;
+import org.hibernate.StaleObjectStateException;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.exception.JDBCExceptionHelper;
+import org.hibernate.persister.entity.Lockable;
+import org.hibernate.pretty.MessageHelper;
+import org.hibernate.sql.Update;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A pessimistic locking strategy where the locks are obtained through update statements.
+ * <p/>
+ * This strategy is valid for LockMode.PESSIMISTIC_READ
+ *
+ * This class is a clone of UpdateLockingStrategy.
+ *
+ * @since 3.5
+ *
+ * @author Steve Ebersole
+ * @author Scott Marlow
+ */
+public class PessimisticReadUpdateLockingStrategy implements LockingStrategy {
+	private static final Logger log = LoggerFactory.getLogger( PessimisticReadUpdateLockingStrategy.class );
+
+	private final Lockable lockable;
+	private final LockMode lockMode;
+	private final String sql;
+
+	/**
+	 * Construct a locking strategy based on SQL UPDATE statements.
+	 *
+	 * @param lockable The metadata for the entity to be locked.
+	 * @param lockMode Indictates the type of lock to be acquired.  Note that
+	 * read-locks are not valid for this strategy.
+	 */
+	public PessimisticReadUpdateLockingStrategy(Lockable lockable, LockMode lockMode) {
+		this.lockable = lockable;
+		this.lockMode = lockMode;
+		if ( lockMode.lessThan( LockMode.PESSIMISTIC_READ ) ) {
+			throw new HibernateException( "[" + lockMode + "] not valid for update statement" );
+		}
+		if ( !lockable.isVersioned() ) {
+			log.warn( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
+			this.sql = null;
+		}
+		else {
+			this.sql = generateLockString();
+		}
+	}
+
+   /**
+	 * @see org.hibernate.dialect.lock.LockingStrategy#lock
+	 */
+	public void lock(
+      Serializable id,
+      Object version,
+      Object object,
+      int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
+		if ( !lockable.isVersioned() ) {
+			throw new HibernateException( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
+		}
+		SessionFactoryImplementor factory = session.getFactory();
+		try {
+			PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
+			try {
+				lockable.getVersionType().nullSafeSet( st, version, 1, session );
+				int offset = 2;
+
+				lockable.getIdentifierType().nullSafeSet( st, id, offset, session );
+				offset += lockable.getIdentifierType().getColumnSpan( factory );
+
+				if ( lockable.isVersioned() ) {
+					lockable.getVersionType().nullSafeSet( st, version, offset, session );
+				}
+
+				int affected = st.executeUpdate();
+				if ( affected < 0 ) {  // todo:  should this instead check for exactly one row modified?
+					factory.getStatisticsImplementor().optimisticFailure( lockable.getEntityName() );
+					throw new StaleObjectStateException( lockable.getEntityName(), id );
+				}
+
+			}
+			finally {
+				session.getBatcher().closeStatement( st );
+			}
+
+		}
+		catch ( SQLException sqle ) {
+			throw JDBCExceptionHelper.convert(
+					session.getFactory().getSQLExceptionConverter(),
+			        sqle,
+			        "could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
+			        sql
+			);
+		}
+	}
+
+	protected String generateLockString() {
+		SessionFactoryImplementor factory = lockable.getFactory();
+		Update update = new Update( factory.getDialect() );
+		update.setTableName( lockable.getRootTableName() );
+		update.addPrimaryKeyColumns( lockable.getRootTableIdentifierColumnNames() );
+		update.setVersionColumnName( lockable.getVersionColumnName() );
+		update.addColumn( lockable.getVersionColumnName() );
+		if ( factory.getSettings().isCommentsEnabled() ) {
+			update.setComment( lockMode + " lock " + lockable.getEntityName() );
+		}
+		return update.toStatementString();
+	}
+
+	protected LockMode getLockMode() {
+		return lockMode;
+	}
+}
\ No newline at end of file

Added: core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteSelectLockingStrategy.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -0,0 +1,148 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.dialect.lock;
+
+import org.hibernate.persister.entity.Lockable;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.StaleObjectStateException;
+import org.hibernate.JDBCException;
+import org.hibernate.LockMode;
+import org.hibernate.sql.SimpleSelect;
+import org.hibernate.pretty.MessageHelper;
+import org.hibernate.exception.JDBCExceptionHelper;
+
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * A pessimistic locking strategy where the locks are obtained through select statements.
+ * <p/>
+ * For non-read locks, this is achieved through the Dialect's specific
+ * SELECT ... FOR UPDATE syntax.
+ * 
+ * This strategy is valid for LockMode.PESSIMISTIC_WRITE
+ *
+ * This class is a clone of SelectLockingStrategy.
+ *
+ * @see org.hibernate.dialect.Dialect#getForUpdateString(org.hibernate.LockMode)
+ * @see org.hibernate.dialect.Dialect#appendLockHint(org.hibernate.LockMode, String)
+ * @since 3.5
+ *
+ * @author Steve Ebersole
+ * @author Scott Marlow
+ */
+public class PessimisticWriteSelectLockingStrategy implements LockingStrategy {
+
+	private final Lockable lockable;
+	private final LockMode lockMode;
+	private final String sql;
+
+	/**
+	 * Construct a locking strategy based on SQL SELECT statements.
+	 *
+	 * @param lockable The metadata for the entity to be locked.
+	 * @param lockMode Indictates the type of lock to be acquired.
+	 */
+	public PessimisticWriteSelectLockingStrategy(Lockable lockable, LockMode lockMode) {
+		this.lockable = lockable;
+		this.lockMode = lockMode;
+		this.sql = generateLockString();
+	}
+
+   /**
+	 * @see LockingStrategy#lock
+	 */
+	public void lock(
+      Serializable id,
+      Object version,
+      Object object,
+      int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
+
+		SessionFactoryImplementor factory = session.getFactory();
+		try {
+			PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
+			try {
+				lockable.getIdentifierType().nullSafeSet( st, id, 1, session );
+				if ( lockable.isVersioned() ) {
+					lockable.getVersionType().nullSafeSet(
+							st,
+							version,
+							lockable.getIdentifierType().getColumnSpan( factory ) + 1,
+							session
+					);
+				}
+
+				ResultSet rs = st.executeQuery();
+				try {
+					if ( !rs.next() ) {
+						if ( factory.getStatistics().isStatisticsEnabled() ) {
+							factory.getStatisticsImplementor()
+									.optimisticFailure( lockable.getEntityName() );
+						}
+						throw new StaleObjectStateException( lockable.getEntityName(), id );
+					}
+				}
+				finally {
+					rs.close();
+				}
+			}
+			finally {
+				session.getBatcher().closeStatement( st );
+			}
+
+		}
+		catch ( SQLException sqle ) {
+			throw JDBCExceptionHelper.convert(
+					session.getFactory().getSQLExceptionConverter(),
+					sqle,
+					"could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
+					sql
+				);
+		}
+	}
+
+	protected LockMode getLockMode() {
+		return lockMode;
+	}
+
+	protected String generateLockString() {
+		SessionFactoryImplementor factory = lockable.getFactory();
+		SimpleSelect select = new SimpleSelect( factory.getDialect() )
+				.setLockMode( lockMode )
+				.setTableName( lockable.getRootTableName() )
+				.addColumn( lockable.getRootTableIdentifierColumnNames()[0] )
+				.addCondition( lockable.getRootTableIdentifierColumnNames(), "=?" );
+		if ( lockable.isVersioned() ) {
+			select.addCondition( lockable.getVersionColumnName(), "=?" );
+		}
+		if ( factory.getSettings().isCommentsEnabled() ) {
+			select.setComment( lockMode + " lock " + lockable.getEntityName() );
+		}
+		return select.toStatementString();
+	}
+}
\ No newline at end of file

Added: core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/PessimisticWriteUpdateLockingStrategy.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -0,0 +1,148 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.dialect.lock;
+
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+import org.hibernate.HibernateException;
+import org.hibernate.JDBCException;
+import org.hibernate.LockMode;
+import org.hibernate.StaleObjectStateException;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.exception.JDBCExceptionHelper;
+import org.hibernate.persister.entity.Lockable;
+import org.hibernate.pretty.MessageHelper;
+import org.hibernate.sql.Update;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A pessimistic locking strategy where the locks are obtained through update statements.
+ * <p/>
+ * This strategy is valid for LockMode.PESSIMISTIC_WRITE
+ *
+ * This class is a clone of UpdateLockingStrategy.
+ *
+ * @since 3.5
+ *
+ * @author Steve Ebersole
+ * @author Scott Marlow
+ */
+public class PessimisticWriteUpdateLockingStrategy implements LockingStrategy {
+	private static final Logger log = LoggerFactory.getLogger( PessimisticWriteUpdateLockingStrategy.class );
+
+	private final Lockable lockable;
+	private final LockMode lockMode;
+	private final String sql;
+
+	/**
+	 * Construct a locking strategy based on SQL UPDATE statements.
+	 *
+	 * @param lockable The metadata for the entity to be locked.
+	 * @param lockMode Indictates the type of lock to be acquired.  Note that
+	 * read-locks are not valid for this strategy.
+	 */
+	public PessimisticWriteUpdateLockingStrategy(Lockable lockable, LockMode lockMode) {
+		this.lockable = lockable;
+		this.lockMode = lockMode;
+		if ( lockMode.lessThan( LockMode.PESSIMISTIC_READ ) ) {
+			throw new HibernateException( "[" + lockMode + "] not valid for update statement" );
+		}
+		if ( !lockable.isVersioned() ) {
+			log.warn( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
+			this.sql = null;
+		}
+		else {
+			this.sql = generateLockString();
+		}
+	}
+
+   /**
+	 * @see LockingStrategy#lock
+	 */
+	public void lock(
+      Serializable id,
+      Object version,
+      Object object,
+      int timeout, SessionImplementor session) throws StaleObjectStateException, JDBCException {
+		if ( !lockable.isVersioned() ) {
+			throw new HibernateException( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
+		}
+		SessionFactoryImplementor factory = session.getFactory();
+		try {
+			PreparedStatement st = session.getBatcher().prepareSelectStatement( sql );
+			try {
+				lockable.getVersionType().nullSafeSet( st, version, 1, session );
+				int offset = 2;
+
+				lockable.getIdentifierType().nullSafeSet( st, id, offset, session );
+				offset += lockable.getIdentifierType().getColumnSpan( factory );
+
+				if ( lockable.isVersioned() ) {
+					lockable.getVersionType().nullSafeSet( st, version, offset, session );
+				}
+
+				int affected = st.executeUpdate();
+				if ( affected < 0 ) {  // todo:  should this instead check for exactly one row modified?
+					factory.getStatisticsImplementor().optimisticFailure( lockable.getEntityName() );
+					throw new StaleObjectStateException( lockable.getEntityName(), id );
+				}
+
+			}
+			finally {
+				session.getBatcher().closeStatement( st );
+			}
+
+		}
+		catch ( SQLException sqle ) {
+			throw JDBCExceptionHelper.convert(
+					session.getFactory().getSQLExceptionConverter(),
+			        sqle,
+			        "could not lock: " + MessageHelper.infoString( lockable, id, session.getFactory() ),
+			        sql
+			);
+		}
+	}
+
+	protected String generateLockString() {
+		SessionFactoryImplementor factory = lockable.getFactory();
+		Update update = new Update( factory.getDialect() );
+		update.setTableName( lockable.getRootTableName() );
+		update.addPrimaryKeyColumns( lockable.getRootTableIdentifierColumnNames() );
+		update.setVersionColumnName( lockable.getVersionColumnName() );
+		update.addColumn( lockable.getVersionColumnName() );
+		if ( factory.getSettings().isCommentsEnabled() ) {
+			update.setComment( lockMode + " lock " + lockable.getEntityName() );
+		}
+		return update.toStatementString();
+	}
+
+	protected LockMode getLockMode() {
+		return lockMode;
+	}
+}
\ No newline at end of file

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/SelectLockingStrategy.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -76,6 +76,7 @@
 	        Serializable id,
 	        Object version,
 	        Object object,
+	        int timeout, 
 	        SessionImplementor session) throws StaleObjectStateException, JDBCException {
 
 		SessionFactoryImplementor factory = session.getFactory();

Modified: core/trunk/core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -83,9 +83,10 @@
 	 * @see LockingStrategy#lock
 	 */
 	public void lock(
-			Serializable id,
+	        Serializable id,
 	        Object version,
 	        Object object,
+	        int timeout,
 	        SessionImplementor session) throws StaleObjectStateException, JDBCException {
 		if ( !lockable.isVersioned() ) {
 			throw new HibernateException( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );

Modified: core/trunk/core/src/main/java/org/hibernate/event/def/AbstractLockUpgradeEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/AbstractLockUpgradeEventListener.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/AbstractLockUpgradeEventListener.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -100,27 +100,13 @@
 			}
 			
 			try {
-				if ( persister.isVersioned() && (requestedLockMode == LockMode.FORCE || requestedLockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT )  ) {
+				if ( persister.isVersioned() && requestedLockMode == LockMode.FORCE  ) {
 					// todo : should we check the current isolation mode explicitly?
 					Object nextVersion = persister.forceVersionIncrement(
 							entry.getId(), entry.getVersion(), source
 					);
 					entry.forceLocked( object, nextVersion );
 				}
-				else if ( requestedLockMode == LockMode.OPTIMISTIC_FORCE_INCREMENT  ) {
-					if(!persister.isVersioned()) {
-						throw new OptimisticLockException("force: Version column is not mapped for " + entry.getPersister().getEntityName(), object);
-					}
-					EntityIncrementVersionProcess incrementVersion = new EntityIncrementVersionProcess(object, entry);
-					source.getActionQueue().registerProcess(incrementVersion);
-				}
-				else if ( requestedLockMode == LockMode.OPTIMISTIC  ) {
-					if(!persister.isVersioned()) {
-						throw new OptimisticLockException("Version column is not mapped for " + entry.getPersister().getEntityName(), object);					
-					}
-					EntityVerifyVersionProcess verifyVersion = new EntityVerifyVersionProcess(object, entry);
-					source.getActionQueue().registerProcess(verifyVersion);
-				}
 				else {
 					persister.lock( entry.getId(), entry.getVersion(), object, requestedLockMode, source );
 				}

Modified: core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java	2009-11-11 22:20:48 UTC (rev 17961)
+++ core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java	2009-11-12 04:20:41 UTC (rev 17962)
@@ -1412,7 +1412,7 @@
 	        Object object,
 	        LockMode lockMode,
 	        SessionImplementor session) throws HibernateException {
-		getLocker( lockMode ).lock( id, version, object, session );
+		getLocker( lockMode ).lock( id, version, object, -1, session );
 	}
 
 	public String getRootTableName() {



More information about the hibernate-commits mailing list