HHH-4546 - add JPA 2.0 locking.
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17962 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
49d529bad8
commit
655be65063
|
@ -126,7 +126,7 @@ public final class LockMode implements Serializable {
|
||||||
* Optimisticly assume that transaction will not experience contention for entities.
|
* Optimisticly assume that transaction will not experience contention for entities.
|
||||||
* The entity version will be verified and incremented near the transaction end.
|
* 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.
|
* Implemented as PESSIMISTIC_WRITE.
|
||||||
|
|
|
@ -41,9 +41,7 @@ import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||||
import org.hibernate.dialect.function.StandardJDBCEscapeFunction;
|
import org.hibernate.dialect.function.StandardJDBCEscapeFunction;
|
||||||
import org.hibernate.dialect.function.ConvertFunction;
|
import org.hibernate.dialect.function.ConvertFunction;
|
||||||
import org.hibernate.dialect.function.ConditionalParenthesisFunction;
|
import org.hibernate.dialect.function.ConditionalParenthesisFunction;
|
||||||
import org.hibernate.dialect.lock.LockingStrategy;
|
import org.hibernate.dialect.lock.*;
|
||||||
import org.hibernate.dialect.lock.SelectLockingStrategy;
|
|
||||||
import org.hibernate.dialect.lock.UpdateLockingStrategy;
|
|
||||||
import org.hibernate.exception.CacheSQLStateConverter;
|
import org.hibernate.exception.CacheSQLStateConverter;
|
||||||
import org.hibernate.exception.SQLExceptionConverter;
|
import org.hibernate.exception.SQLExceptionConverter;
|
||||||
import org.hibernate.exception.TemplatedViolatedConstraintNameExtracter;
|
import org.hibernate.exception.TemplatedViolatedConstraintNameExtracter;
|
||||||
|
@ -564,7 +562,22 @@ public class Cache71Dialect extends Dialect {
|
||||||
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
||||||
// InterSystems Cache' does not current support "SELECT ... FOR UPDATE" syntax...
|
// InterSystems Cache' does not current support "SELECT ... FOR UPDATE" syntax...
|
||||||
// Set your transaction mode to READ_COMMITTED before using
|
// 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 );
|
return new UpdateLockingStrategy( lockable, lockMode );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -48,8 +48,7 @@ import org.hibernate.dialect.function.CastFunction;
|
||||||
import org.hibernate.dialect.function.SQLFunction;
|
import org.hibernate.dialect.function.SQLFunction;
|
||||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
import org.hibernate.dialect.lock.LockingStrategy;
|
import org.hibernate.dialect.lock.*;
|
||||||
import org.hibernate.dialect.lock.SelectLockingStrategy;
|
|
||||||
import org.hibernate.engine.Mapping;
|
import org.hibernate.engine.Mapping;
|
||||||
import org.hibernate.engine.SessionFactoryImplementor;
|
import org.hibernate.engine.SessionFactoryImplementor;
|
||||||
import org.hibernate.exception.SQLExceptionConverter;
|
import org.hibernate.exception.SQLExceptionConverter;
|
||||||
|
@ -952,6 +951,21 @@ public abstract class Dialect {
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
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 );
|
return new SelectLockingStrategy( lockable, lockMode );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
import org.hibernate.dialect.lock.LockingStrategy;
|
import org.hibernate.dialect.lock.*;
|
||||||
import org.hibernate.dialect.lock.UpdateLockingStrategy;
|
|
||||||
import org.hibernate.dialect.lock.SelectLockingStrategy;
|
|
||||||
import org.hibernate.persister.entity.Lockable;
|
import org.hibernate.persister.entity.Lockable;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
|
||||||
|
@ -104,7 +102,22 @@ public class FrontBaseDialect extends Dialect {
|
||||||
|
|
||||||
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
||||||
// Frontbase has no known variation of a "SELECT ... FOR UPDATE" syntax...
|
// 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 );
|
return new UpdateLockingStrategy( lockable, lockMode );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -38,8 +38,7 @@ import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||||
import org.hibernate.dialect.lock.LockingStrategy;
|
import org.hibernate.dialect.lock.*;
|
||||||
import org.hibernate.dialect.lock.SelectLockingStrategy;
|
|
||||||
import org.hibernate.exception.JDBCExceptionHelper;
|
import org.hibernate.exception.JDBCExceptionHelper;
|
||||||
import org.hibernate.exception.TemplatedViolatedConstraintNameExtracter;
|
import org.hibernate.exception.TemplatedViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.exception.ViolatedConstraintNameExtracter;
|
import org.hibernate.exception.ViolatedConstraintNameExtracter;
|
||||||
|
@ -292,7 +291,17 @@ public class HSQLDialect extends Dialect {
|
||||||
|
|
||||||
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
||||||
// HSQLDB only supports READ_UNCOMMITTED transaction isolation
|
// 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 );
|
return new ReadUncommittedLockingStrategy( lockable, lockMode );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ReadUncommittedLockingStrategy extends SelectLockingStrategy {
|
public static class ReadUncommittedLockingStrategy extends SelectLockingStrategy {
|
||||||
|
@ -300,12 +309,12 @@ public class HSQLDialect extends Dialect {
|
||||||
super( lockable, lockMode );
|
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 {
|
throws StaleObjectStateException, JDBCException {
|
||||||
if ( getLockMode().greaterThan( LockMode.READ ) ) {
|
if ( getLockMode().greaterThan( LockMode.READ ) ) {
|
||||||
log.warn( "HSQLDB supports only READ_UNCOMMITTED isolation" );
|
log.warn( "HSQLDB supports only READ_UNCOMMITTED isolation" );
|
||||||
}
|
}
|
||||||
super.lock( id, version, object, session );
|
super.lock( id, version, object, timeout, session );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,7 @@ import org.hibernate.LockMode;
|
||||||
import org.hibernate.persister.entity.Lockable;
|
import org.hibernate.persister.entity.Lockable;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
import org.hibernate.dialect.lock.LockingStrategy;
|
import org.hibernate.dialect.lock.*;
|
||||||
import org.hibernate.dialect.lock.UpdateLockingStrategy;
|
|
||||||
import org.hibernate.dialect.lock.SelectLockingStrategy;
|
|
||||||
import org.hibernate.sql.CaseFragment;
|
import org.hibernate.sql.CaseFragment;
|
||||||
import org.hibernate.sql.MckoiCaseFragment;
|
import org.hibernate.sql.MckoiCaseFragment;
|
||||||
|
|
||||||
|
@ -111,7 +109,22 @@ public class MckoiDialect extends Dialect {
|
||||||
|
|
||||||
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
||||||
// Mckoi has no known variation of a "SELECT ... FOR UPDATE" syntax...
|
// 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 );
|
return new UpdateLockingStrategy( lockable, lockMode );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -24,9 +24,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
import org.hibernate.dialect.lock.LockingStrategy;
|
import org.hibernate.dialect.lock.*;
|
||||||
import org.hibernate.dialect.lock.UpdateLockingStrategy;
|
|
||||||
import org.hibernate.dialect.lock.SelectLockingStrategy;
|
|
||||||
import org.hibernate.persister.entity.Lockable;
|
import org.hibernate.persister.entity.Lockable;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
|
||||||
|
@ -81,7 +79,22 @@ public class PointbaseDialect extends org.hibernate.dialect.Dialect {
|
||||||
|
|
||||||
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
||||||
// Pointbase has no known variation of a "SELECT ... FOR UPDATE" syntax...
|
// 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 );
|
return new UpdateLockingStrategy( lockable, lockMode );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -27,9 +27,7 @@ package org.hibernate.dialect;
|
||||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||||
import org.hibernate.dialect.lock.LockingStrategy;
|
import org.hibernate.dialect.lock.*;
|
||||||
import org.hibernate.dialect.lock.UpdateLockingStrategy;
|
|
||||||
import org.hibernate.dialect.lock.SelectLockingStrategy;
|
|
||||||
|
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
|
@ -336,7 +334,22 @@ public class RDMSOS2200Dialect extends Dialect {
|
||||||
|
|
||||||
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
||||||
// RDMS has no known variation of a "SELECT ... FOR UPDATE" syntax...
|
// 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 );
|
return new UpdateLockingStrategy( lockable, lockMode );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -111,10 +111,15 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String appendLockHint(LockMode mode, String tableName) {
|
public String appendLockHint(LockMode mode, String tableName) {
|
||||||
if ( mode.greaterThan( LockMode.READ ) ) {
|
if ( ( mode == LockMode.UPGRADE ) ||
|
||||||
// does this need holdlock also? : return tableName + " with (updlock, rowlock, holdlock)";
|
( mode == LockMode.UPGRADE_NOWAIT ) ||
|
||||||
|
( mode == LockMode.PESSIMISTIC_WRITE ) ||
|
||||||
|
( mode == LockMode.WRITE ) ) {
|
||||||
return tableName + " with (updlock, rowlock)";
|
return tableName + " with (updlock, rowlock)";
|
||||||
}
|
}
|
||||||
|
else if ( mode == LockMode.PESSIMISTIC_READ ) {
|
||||||
|
return tableName + " with (holdlock, rowlock)";
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return tableName;
|
return tableName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,7 @@ import org.hibernate.persister.entity.Lockable;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
import org.hibernate.dialect.lock.LockingStrategy;
|
import org.hibernate.dialect.lock.*;
|
||||||
import org.hibernate.dialect.lock.UpdateLockingStrategy;
|
|
||||||
import org.hibernate.dialect.lock.SelectLockingStrategy;
|
|
||||||
import org.hibernate.sql.JoinFragment;
|
import org.hibernate.sql.JoinFragment;
|
||||||
import org.hibernate.sql.OracleJoinFragment;
|
import org.hibernate.sql.OracleJoinFragment;
|
||||||
|
|
||||||
|
@ -217,7 +215,22 @@ public class TimesTenDialect extends Dialect {
|
||||||
|
|
||||||
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
|
||||||
// TimesTen has no known variation of a "SELECT ... FOR UPDATE" syntax...
|
// 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 );
|
return new UpdateLockingStrategy( lockable, lockMode );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -51,11 +51,12 @@ public interface LockingStrategy {
|
||||||
* @param id The id of the row to be locked
|
* @param id The id of the row to be locked
|
||||||
* @param version The current version (or null if not versioned)
|
* @param version The current version (or null if not versioned)
|
||||||
* @param object The object logically being locked (currently not used)
|
* @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
|
* @param session The session from which the lock request originated
|
||||||
* @throws StaleObjectStateException Indicates an optimisitic lock failure
|
* @throws StaleObjectStateException Indicates an optimisitic lock failure
|
||||||
* as part of acquiring the requested database lock.
|
* as part of acquiring the requested database lock.
|
||||||
* @throws JDBCException
|
* @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;
|
throws StaleObjectStateException, JDBCException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -76,6 +76,7 @@ public class SelectLockingStrategy implements LockingStrategy {
|
||||||
Serializable id,
|
Serializable id,
|
||||||
Object version,
|
Object version,
|
||||||
Object object,
|
Object object,
|
||||||
|
int timeout,
|
||||||
SessionImplementor session) throws StaleObjectStateException, JDBCException {
|
SessionImplementor session) throws StaleObjectStateException, JDBCException {
|
||||||
|
|
||||||
SessionFactoryImplementor factory = session.getFactory();
|
SessionFactoryImplementor factory = session.getFactory();
|
||||||
|
|
|
@ -86,6 +86,7 @@ public class UpdateLockingStrategy implements LockingStrategy {
|
||||||
Serializable id,
|
Serializable id,
|
||||||
Object version,
|
Object version,
|
||||||
Object object,
|
Object object,
|
||||||
|
int timeout,
|
||||||
SessionImplementor session) throws StaleObjectStateException, JDBCException {
|
SessionImplementor session) throws StaleObjectStateException, JDBCException {
|
||||||
if ( !lockable.isVersioned() ) {
|
if ( !lockable.isVersioned() ) {
|
||||||
throw new HibernateException( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
|
throw new HibernateException( "write locks via update not supported for non-versioned entities [" + lockable.getEntityName() + "]" );
|
||||||
|
|
|
@ -100,27 +100,13 @@ public class AbstractLockUpgradeEventListener extends AbstractReassociateEventLi
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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?
|
// todo : should we check the current isolation mode explicitly?
|
||||||
Object nextVersion = persister.forceVersionIncrement(
|
Object nextVersion = persister.forceVersionIncrement(
|
||||||
entry.getId(), entry.getVersion(), source
|
entry.getId(), entry.getVersion(), source
|
||||||
);
|
);
|
||||||
entry.forceLocked( object, nextVersion );
|
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 {
|
else {
|
||||||
persister.lock( entry.getId(), entry.getVersion(), object, requestedLockMode, source );
|
persister.lock( entry.getId(), entry.getVersion(), object, requestedLockMode, source );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1412,7 +1412,7 @@ public abstract class AbstractEntityPersister
|
||||||
Object object,
|
Object object,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
SessionImplementor session) throws HibernateException {
|
SessionImplementor session) throws HibernateException {
|
||||||
getLocker( lockMode ).lock( id, version, object, session );
|
getLocker( lockMode ).lock( id, version, object, -1, session );
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRootTableName() {
|
public String getRootTableName() {
|
||||||
|
|
Loading…
Reference in New Issue