Author: smarlow(a)redhat.com
Date: 2009-12-11 08:23:17 -0500 (Fri, 11 Dec 2009)
New Revision: 18209
Modified:
core/trunk/core/src/main/java/org/hibernate/PessimisticLockException.java
core/trunk/core/src/main/java/org/hibernate/exception/SQLStateConverter.java
core/trunk/core/src/main/java/org/hibernate/loader/Loader.java
core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinLoader.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
Log:
HHH-4546 JPA-2.0 locking. More pessimistic lock exception support and timeout exception
support
Modified: core/trunk/core/src/main/java/org/hibernate/PessimisticLockException.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/PessimisticLockException.java 2009-12-11
12:40:05 UTC (rev 18208)
+++ core/trunk/core/src/main/java/org/hibernate/PessimisticLockException.java 2009-12-11
13:23:17 UTC (rev 18209)
@@ -24,29 +24,33 @@
*/
package org.hibernate;
+import java.sql.SQLException;
+
/**
*
- * Throw when an pessimistic locking conflict occurs.
+ * Thrown when a pessimistic locking conflict occurs.
*
* @author Scott Marlow
*/
-public class PessimisticLockException extends HibernateException {
+public class PessimisticLockException extends JDBCException {
Object entity;
- public PessimisticLockException(String s) {
- super(s);
- }
- public PessimisticLockException(String s, Throwable throwable, Object entity) {
- super(s, throwable);
+ public PessimisticLockException(String s, JDBCException je, Object entity) {
+ super(s, je.getSQLException());
+ this.entity = entity;
+ }
+
+ public PessimisticLockException(String s, SQLException se, Object entity) {
+ super(s, se);
this.entity = entity;
}
- public PessimisticLockException(String s, Object entity) {
- super(s);
- this.entity = entity;
- }
+ public PessimisticLockException(String s, SQLException se, String sql) {
+ super(s, se, sql);
+ this.entity = null;
+ }
public Object getEntity() {
return entity;
Modified: core/trunk/core/src/main/java/org/hibernate/exception/SQLStateConverter.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/exception/SQLStateConverter.java 2009-12-11
12:40:05 UTC (rev 18208)
+++
core/trunk/core/src/main/java/org/hibernate/exception/SQLStateConverter.java 2009-12-11
13:23:17 UTC (rev 18209)
@@ -25,6 +25,7 @@
package org.hibernate.exception;
import org.hibernate.JDBCException;
+import org.hibernate.PessimisticLockException;
import java.sql.SQLException;
import java.util.HashSet;
@@ -109,6 +110,11 @@
// oracle sql-state code for deadlock
return new LockAcquisitionException( message, sqlException, sql );
}
+
+ if ( "40XL1".equals( sqlState ) || "40XL2".equals( sqlState )) {
+ // Derby "A lock could not be obtained within the time requested."
+ return new PessimisticLockException( message, sqlException, sql );
+ }
}
return handledNonSpecificException( sqlException, message, sql );
Modified: core/trunk/core/src/main/java/org/hibernate/loader/Loader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/Loader.java 2009-12-11 12:40:05 UTC
(rev 18208)
+++ core/trunk/core/src/main/java/org/hibernate/loader/Loader.java 2009-12-11 13:23:17 UTC
(rev 18209)
@@ -214,14 +214,35 @@
return null;
}
+ private Map buildLockMap(Map locks) {
+ Map result = locks;
+ if ( result == null ) {
+ LockOptions[] lockArray = getLockOptions(result);
+ String[] aliases = getAliases();
+ if (aliases != null &&
+ lockArray != null &&
+ lockArray.length > 0 &&
+ lockArray.length == aliases.length &&
+ lockArray[0].getLockMode() != LockMode.NONE ) {
+ result = new HashMap();
+ for ( int looper = 0; looper < lockArray.length; looper++ ) {
+ result.put(aliases[looper], lockArray[looper]);
+ }
+ }
+ }
+
+ return result;
+ }
/**
* Modify the SQL, adding lock hints and comments, if necessary
*/
protected String preprocessSQL(String sql, QueryParameters parameters, Dialect dialect)
throws HibernateException {
+
+ Map locks = buildLockMap(parameters.getLockOptions());
+
+ sql = applyLocks( sql, locks, dialect );
- sql = applyLocks( sql, parameters.getLockOptions(), dialect );
-
return getFactory().getSettings().isCommentsEnabled() ?
prependComment( sql, parameters ) : sql;
}
@@ -700,9 +721,9 @@
//
// Would need to change the way the max-row stuff is handled (i.e. behind an interface)
so
// that I could do the control breaking at the means to know when to stop
+
+ final EntityKey optionalObjectKey = getOptionalObjectKey( queryParameters, session );
final LockOptions[] lockOptionsArray = getLockOptions( queryParameters.getLockOptions()
);
- final EntityKey optionalObjectKey = getOptionalObjectKey( queryParameters, session );
-
final boolean createSubselects = isSubselectLoadingEnabled();
final List subselectResultKeys = createSubselects ? new ArrayList() : null;
final List results = new ArrayList();
Modified: core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinLoader.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinLoader.java 2009-12-11
12:40:05 UTC (rev 18208)
+++ core/trunk/core/src/main/java/org/hibernate/loader/OuterJoinLoader.java 2009-12-11
13:23:17 UTC (rev 18209)
@@ -25,9 +25,7 @@
package org.hibernate.loader;
import java.util.Map;
-import java.util.Set;
-import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionFactoryImplementor;
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
===================================================================
---
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2009-12-11
12:40:05 UTC (rev 18208)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2009-12-11
13:23:17 UTC (rev 18209)
@@ -257,9 +257,11 @@
}
public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType
lockModeType, Map<String, Object> properties) {
+ LockOptions lockOptions = null;
try {
if ( lockModeType != null )
- return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey,
getLockRequest(lockModeType, properties) );
+ return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey,
+ ( lockOptions = getLockRequest(lockModeType, properties) ) );
else
return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey );
}
@@ -281,7 +283,7 @@
throw new IllegalArgumentException( e.getMessage(), e );
}
catch ( HibernateException he ) {
- throw convert( he );
+ throw convert( he , lockOptions );
}
}
@@ -351,12 +353,13 @@
public void refresh(Object entity, LockModeType lockModeType, Map<String, Object>
properties) {
checkTransactionNeeded();
+ LockOptions lockOptions = null;
try {
if ( !getSession().contains( entity ) ) {
throw new IllegalArgumentException( "Entity not managed" );
}
if(lockModeType != null)
- getSession().refresh( entity, getLockRequest(lockModeType, properties) );
+ getSession().refresh( entity, (lockOptions = getLockRequest(lockModeType, properties)
) );
else
getSession().refresh( entity );
}
@@ -364,7 +367,7 @@
throw new IllegalArgumentException( e.getMessage(), e );
}
catch ( HibernateException he ) {
- throw convert( he );
+ throw convert( he, lockOptions);
}
}
@@ -515,6 +518,7 @@
}
public void lock(Object entity, LockModeType lockModeType, Map<String, Object>
properties) {
+ LockOptions lockOptions = null;
try {
if ( !isTransactionInProgress() ) {
throw new TransactionRequiredException( "no transaction is in progress" );
@@ -523,10 +527,10 @@
if ( !contains( entity ) ) {
throw new IllegalArgumentException( "entity not in the persistence context"
);
}
- getSession().buildLockRequest(getLockRequest(lockModeType, properties)).lock( entity
);
+ getSession().buildLockRequest( (lockOptions = getLockRequest(lockModeType,
properties))).lock( entity );
}
catch ( HibernateException he ) {
- throw convert( he );
+ throw convert( he , lockOptions);
}
}
@@ -835,18 +839,25 @@
* {@inheritDoc}
*/
public RuntimeException convert(HibernateException e) {
+ return convert(e, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public RuntimeException convert(HibernateException e, LockOptions lockOptions) {
if ( e instanceof StaleStateException ) {
PersistenceException converted = wrapStaleStateException( ( StaleStateException ) e
);
handlePersistenceException( converted );
return converted;
}
else if ( e instanceof org.hibernate.OptimisticLockException ) {
- PersistenceException converted = wrapLockException(e);
+ PersistenceException converted = wrapLockException(e, lockOptions);
handlePersistenceException( converted );
return converted;
}
else if ( e instanceof org.hibernate.PessimisticLockException ) {
- PersistenceException converted = wrapLockException(e);
+ PersistenceException converted = wrapLockException(e, lockOptions);
handlePersistenceException( converted );
return converted;
}
@@ -925,7 +936,7 @@
return pe;
}
- public PersistenceException wrapLockException(HibernateException e) {
+ public PersistenceException wrapLockException(HibernateException e, LockOptions
lockOptions) {
PersistenceException pe;
if ( e instanceof org.hibernate.OptimisticLockException ) {
org.hibernate.OptimisticLockException ole =
(org.hibernate.OptimisticLockException)e;
@@ -933,7 +944,13 @@
}
else if ( e instanceof org.hibernate.PessimisticLockException ) {
org.hibernate.PessimisticLockException ple =
(org.hibernate.PessimisticLockException)e;
- pe = new PessimisticLockException(ple.getMessage(), ple, ple.getEntity());
+ if (lockOptions !=null && lockOptions.getTimeOut() > -1) {
+ // assume lock timeout occurred if a timeout or NO WAIT was specified
+ pe = new LockTimeoutException(ple.getMessage(), ple, ple.getEntity());
+ }
+ else {
+ pe = new PessimisticLockException(ple.getMessage(), ple, ple.getEntity());
+ }
}
else {
pe = new OptimisticLockException( e );
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
===================================================================
---
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java 2009-12-11
12:40:05 UTC (rev 18208)
+++
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java 2009-12-11
13:23:17 UTC (rev 18209)
@@ -27,6 +27,7 @@
import org.hibernate.HibernateException;
import org.hibernate.StaleStateException;
+import org.hibernate.LockOptions;
/**
* Additional internal contracts for the Hibernate {@link
javax.persistence.EntityManager} implementation.
@@ -64,8 +65,20 @@
* Any appropriate/needed calls to {@link #handlePersistenceException} are also made.
*
* @param e The Hibernate excepton.
+ * @param lockOptions The lock options in effect at the time of exception (can be null)
* @return The JPA-specified exception
*/
+ public RuntimeException convert(HibernateException e, LockOptions lockOptions);
+
+ /**
+ * Converts a Hibernate-specific exception into a JPA-specified exception; note that the
JPA sepcification makes use
+ * of exceptions outside its exception hierarchy, though they are all runtime
exceptions.
+ * <p/>
+ * Any appropriate/needed calls to {@link #handlePersistenceException} are also made.
+ *
+ * @param e The Hibernate excepton.
+ * @return The JPA-specified exception
+ */
public RuntimeException convert(HibernateException e);
/**