diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerImpl.java index d675b07ffe..d5a2961262 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/EntityManagerImpl.java @@ -104,7 +104,7 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess public void checkOpen(boolean markForRollbackIfClosed) { if( ! isOpen() ) { if ( markForRollbackIfClosed ) { - markAsRollback(); + markForRollbackOnly(); } throw new IllegalStateException( "EntityManager is closed" ); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java index e0c629572c..d00a4096d8 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java @@ -40,6 +40,7 @@ import java.util.List; import org.hibernate.CacheMode; import org.hibernate.FlushMode; +import org.hibernate.HibernateException; import org.hibernate.LockMode; import org.hibernate.jpa.spi.ParameterBind; import org.hibernate.jpa.spi.ParameterRegistration; @@ -122,12 +123,23 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro @SuppressWarnings("unchecked") public StoredProcedureQuery registerStoredProcedureParameter(int position, Class type, ParameterMode mode) { entityManager().checkOpen( true ); - registerParameter( - new ParameterRegistrationImpl( - this, - procedureCall.registerParameter( position, type, mode ) - ) - ); + + try { + registerParameter( + new ParameterRegistrationImpl( + this, + procedureCall.registerParameter( position, type, mode ) + ) + ); + } + catch (HibernateException he) { + throw entityManager().convert( he ); + } + catch (RuntimeException e) { + entityManager().markForRollbackOnly(); + throw e; + } + return this; } @@ -135,12 +147,23 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro @SuppressWarnings("unchecked") public StoredProcedureQuery registerStoredProcedureParameter(String parameterName, Class type, ParameterMode mode) { entityManager().checkOpen( true ); - registerParameter( - new ParameterRegistrationImpl( - this, - procedureCall.registerParameter( parameterName, type, mode ) - ) - ); + + try { + registerParameter( + new ParameterRegistrationImpl( + this, + procedureCall.registerParameter( parameterName, type, mode ) + ) + ); + } + catch (HibernateException he) { + throw entityManager().convert( he ); + } + catch (RuntimeException e) { + entityManager().markForRollbackOnly(); + throw e; + } + return this; } @@ -214,6 +237,13 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro catch (NoMoreReturnsException e) { return false; } + catch (HibernateException he) { + throw entityManager().convert( he ); + } + catch (RuntimeException e) { + entityManager().markForRollbackOnly(); + throw e; + } } protected ProcedureOutputs outputs() { @@ -241,6 +271,7 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro @Override public Object getOutputParameterValue(int position) { + // NOTE : according to spec (specifically), an exception thrown from this method should not mark for rollback. try { return outputs().getOutputParameterValue( position ); } @@ -254,6 +285,7 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro @Override public Object getOutputParameterValue(String parameterName) { + // NOTE : according to spec (specifically), an exception thrown from this method should not mark for rollback. try { return outputs().getOutputParameterValue( parameterName ); } @@ -287,6 +319,13 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro catch (NoMoreReturnsException e) { return -1; } + catch (HibernateException he) { + throw entityManager().convert( he ); + } + catch (RuntimeException e) { + entityManager().markForRollbackOnly(); + throw e; + } } @Override @@ -305,6 +344,13 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro // getResultList was called. return null; } + catch (HibernateException he) { + throw entityManager().convert( he ); + } + catch (RuntimeException e) { + entityManager().markForRollbackOnly(); + throw e; + } } @Override diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractEntityManagerImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractEntityManagerImpl.java index 2ee93c5bfc..a81463cde1 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractEntityManagerImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractEntityManagerImpl.java @@ -1379,7 +1379,8 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage throw new PersistenceException( "Hibernate cannot unwrap " + clazz ); } - protected void markAsRollback() { + @Override + public void markForRollbackOnly() { LOG.debugf("Mark transaction for rollback"); if ( tx.isActive() ) { tx.setRollbackOnly(); @@ -1511,7 +1512,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage } try { - markAsRollback(); + markForRollbackOnly(); } catch ( Exception ne ) { //we do not want the subsequent exception to swallow the original one @@ -1537,7 +1538,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage result = convert( ( HibernateException ) e ); } else { - markAsRollback(); + markForRollbackOnly(); } return result; } @@ -1594,7 +1595,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage } else if ( e instanceof TransientObjectException ) { try { - markAsRollback(); + markForRollbackOnly(); } catch ( Exception ne ) { //we do not want the subsequent exception to swallow the original one diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/BaseQueryImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/BaseQueryImpl.java index aa3c625b56..6a78f200ef 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/BaseQueryImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/BaseQueryImpl.java @@ -491,7 +491,8 @@ public abstract class BaseQueryImpl implements Query { findParameterRegistration( param ).bindValue( value ); } catch (QueryParameterException e) { - throw new IllegalArgumentException( e ); + entityManager().markForRollbackOnly(); + throw new IllegalArgumentException( e.getMessage(), e ); } catch (HibernateException he) { throw entityManager.convert( he ); @@ -508,7 +509,8 @@ public abstract class BaseQueryImpl implements Query { findParameterRegistration( param ).bindValue( value, temporalType ); } catch (QueryParameterException e) { - throw new IllegalArgumentException( e ); + entityManager().markForRollbackOnly(); + throw new IllegalArgumentException( e.getMessage(), e ); } catch (HibernateException he) { throw entityManager.convert( he ); @@ -525,7 +527,8 @@ public abstract class BaseQueryImpl implements Query { findParameterRegistration( param ).bindValue( value, temporalType ); } catch (QueryParameterException e) { - throw new IllegalArgumentException( e ); + entityManager().markForRollbackOnly(); + throw new IllegalArgumentException( e.getMessage(), e ); } catch (HibernateException he) { throw entityManager.convert( he ); @@ -543,7 +546,8 @@ public abstract class BaseQueryImpl implements Query { findParameterRegistration( name ).bindValue( value ); } catch (QueryParameterException e) { - throw new IllegalArgumentException( e ); + entityManager().markForRollbackOnly(); + throw new IllegalArgumentException( e.getMessage(), e ); } catch (HibernateException he) { throw entityManager.convert( he ); @@ -560,7 +564,8 @@ public abstract class BaseQueryImpl implements Query { findParameterRegistration( name ).bindValue( value, temporalType ); } catch (QueryParameterException e) { - throw new IllegalArgumentException( e ); + entityManager().markForRollbackOnly(); + throw new IllegalArgumentException( e.getMessage(), e ); } catch (HibernateException he) { throw entityManager.convert( he ); @@ -577,7 +582,8 @@ public abstract class BaseQueryImpl implements Query { findParameterRegistration( name ).bindValue( value, temporalType ); } catch (QueryParameterException e) { - throw new IllegalArgumentException( e ); + entityManager().markForRollbackOnly(); + throw new IllegalArgumentException( e.getMessage(), e ); } catch (HibernateException he) { throw entityManager.convert( he ); @@ -594,7 +600,8 @@ public abstract class BaseQueryImpl implements Query { findParameterRegistration( position ).bindValue( value ); } catch (QueryParameterException e) { - throw new IllegalArgumentException( e ); + entityManager().markForRollbackOnly(); + throw new IllegalArgumentException( e.getMessage(), e ); } catch (HibernateException he) { throw entityManager.convert( he ); @@ -611,7 +618,8 @@ public abstract class BaseQueryImpl implements Query { findParameterRegistration( position ).bindValue( value, temporalType ); } catch (QueryParameterException e) { - throw new IllegalArgumentException( e ); + entityManager().markForRollbackOnly(); + throw new IllegalArgumentException( e.getMessage(), e ); } catch (HibernateException he) { throw entityManager.convert( he ); @@ -628,13 +636,16 @@ public abstract class BaseQueryImpl implements Query { findParameterRegistration( position ).bindValue( value, temporalType ); } catch (ParameterStrategyException e) { + entityManager().markForRollbackOnly(); throw new IllegalArgumentException( "Invalid mix of named and positional parameters", e ); } catch (NoSuchParameterException e) { + entityManager().markForRollbackOnly(); throw new IllegalArgumentException( e.getMessage(), e ); } catch (QueryParameterException e) { - throw new IllegalArgumentException( e ); + entityManager().markForRollbackOnly(); + throw new IllegalArgumentException( e.getMessage(), e ); } catch (HibernateException he) { throw entityManager.convert( he ); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/HibernateEntityManagerImplementor.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/HibernateEntityManagerImplementor.java index 47eb9e32df..64cd3ef0e1 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/HibernateEntityManagerImplementor.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/HibernateEntityManagerImplementor.java @@ -72,6 +72,11 @@ public interface HibernateEntityManagerImplementor extends HibernateEntityManage */ boolean isTransactionInProgress(); + /** + * Used to mark a transaction for rollback only (when that is the JPA spec defined behavior). + */ + public void markForRollbackOnly(); + /** * Handles marking for rollback and other such operations that need to occur depending on the type of * exception being handled.