HHH-8442 - StoredProcedureQuery.execute() should rollback the TX for certain exceptions

This commit is contained in:
Steve Ebersole 2013-08-25 21:03:56 -05:00
parent 1a59e9194b
commit e42e786e8d
5 changed files with 89 additions and 26 deletions

View File

@ -104,7 +104,7 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
public void checkOpen(boolean markForRollbackIfClosed) { public void checkOpen(boolean markForRollbackIfClosed) {
if( ! isOpen() ) { if( ! isOpen() ) {
if ( markForRollbackIfClosed ) { if ( markForRollbackIfClosed ) {
markAsRollback(); markForRollbackOnly();
} }
throw new IllegalStateException( "EntityManager is closed" ); throw new IllegalStateException( "EntityManager is closed" );
} }

View File

@ -40,6 +40,7 @@ import java.util.List;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.jpa.spi.ParameterBind; import org.hibernate.jpa.spi.ParameterBind;
import org.hibernate.jpa.spi.ParameterRegistration; import org.hibernate.jpa.spi.ParameterRegistration;
@ -122,12 +123,23 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public StoredProcedureQuery registerStoredProcedureParameter(int position, Class type, ParameterMode mode) { public StoredProcedureQuery registerStoredProcedureParameter(int position, Class type, ParameterMode mode) {
entityManager().checkOpen( true ); entityManager().checkOpen( true );
try {
registerParameter( registerParameter(
new ParameterRegistrationImpl( new ParameterRegistrationImpl(
this, this,
procedureCall.registerParameter( position, type, mode ) procedureCall.registerParameter( position, type, mode )
) )
); );
}
catch (HibernateException he) {
throw entityManager().convert( he );
}
catch (RuntimeException e) {
entityManager().markForRollbackOnly();
throw e;
}
return this; return this;
} }
@ -135,12 +147,23 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public StoredProcedureQuery registerStoredProcedureParameter(String parameterName, Class type, ParameterMode mode) { public StoredProcedureQuery registerStoredProcedureParameter(String parameterName, Class type, ParameterMode mode) {
entityManager().checkOpen( true ); entityManager().checkOpen( true );
try {
registerParameter( registerParameter(
new ParameterRegistrationImpl( new ParameterRegistrationImpl(
this, this,
procedureCall.registerParameter( parameterName, type, mode ) procedureCall.registerParameter( parameterName, type, mode )
) )
); );
}
catch (HibernateException he) {
throw entityManager().convert( he );
}
catch (RuntimeException e) {
entityManager().markForRollbackOnly();
throw e;
}
return this; return this;
} }
@ -214,6 +237,13 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
catch (NoMoreReturnsException e) { catch (NoMoreReturnsException e) {
return false; return false;
} }
catch (HibernateException he) {
throw entityManager().convert( he );
}
catch (RuntimeException e) {
entityManager().markForRollbackOnly();
throw e;
}
} }
protected ProcedureOutputs outputs() { protected ProcedureOutputs outputs() {
@ -241,6 +271,7 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
@Override @Override
public Object getOutputParameterValue(int position) { public Object getOutputParameterValue(int position) {
// NOTE : according to spec (specifically), an exception thrown from this method should not mark for rollback.
try { try {
return outputs().getOutputParameterValue( position ); return outputs().getOutputParameterValue( position );
} }
@ -254,6 +285,7 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
@Override @Override
public Object getOutputParameterValue(String parameterName) { public Object getOutputParameterValue(String parameterName) {
// NOTE : according to spec (specifically), an exception thrown from this method should not mark for rollback.
try { try {
return outputs().getOutputParameterValue( parameterName ); return outputs().getOutputParameterValue( parameterName );
} }
@ -287,6 +319,13 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
catch (NoMoreReturnsException e) { catch (NoMoreReturnsException e) {
return -1; return -1;
} }
catch (HibernateException he) {
throw entityManager().convert( he );
}
catch (RuntimeException e) {
entityManager().markForRollbackOnly();
throw e;
}
} }
@Override @Override
@ -305,6 +344,13 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
// getResultList was called. // getResultList was called.
return null; return null;
} }
catch (HibernateException he) {
throw entityManager().convert( he );
}
catch (RuntimeException e) {
entityManager().markForRollbackOnly();
throw e;
}
} }
@Override @Override

View File

@ -1379,7 +1379,8 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
throw new PersistenceException( "Hibernate cannot unwrap " + clazz ); throw new PersistenceException( "Hibernate cannot unwrap " + clazz );
} }
protected void markAsRollback() { @Override
public void markForRollbackOnly() {
LOG.debugf("Mark transaction for rollback"); LOG.debugf("Mark transaction for rollback");
if ( tx.isActive() ) { if ( tx.isActive() ) {
tx.setRollbackOnly(); tx.setRollbackOnly();
@ -1511,7 +1512,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
try { try {
markAsRollback(); markForRollbackOnly();
} }
catch ( Exception ne ) { catch ( Exception ne ) {
//we do not want the subsequent exception to swallow the original one //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 ); result = convert( ( HibernateException ) e );
} }
else { else {
markAsRollback(); markForRollbackOnly();
} }
return result; return result;
} }
@ -1594,7 +1595,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
else if ( e instanceof TransientObjectException ) { else if ( e instanceof TransientObjectException ) {
try { try {
markAsRollback(); markForRollbackOnly();
} }
catch ( Exception ne ) { catch ( Exception ne ) {
//we do not want the subsequent exception to swallow the original one //we do not want the subsequent exception to swallow the original one

View File

@ -491,7 +491,8 @@ public abstract class BaseQueryImpl implements Query {
findParameterRegistration( param ).bindValue( value ); findParameterRegistration( param ).bindValue( value );
} }
catch (QueryParameterException e) { catch (QueryParameterException e) {
throw new IllegalArgumentException( e ); entityManager().markForRollbackOnly();
throw new IllegalArgumentException( e.getMessage(), e );
} }
catch (HibernateException he) { catch (HibernateException he) {
throw entityManager.convert( he ); throw entityManager.convert( he );
@ -508,7 +509,8 @@ public abstract class BaseQueryImpl implements Query {
findParameterRegistration( param ).bindValue( value, temporalType ); findParameterRegistration( param ).bindValue( value, temporalType );
} }
catch (QueryParameterException e) { catch (QueryParameterException e) {
throw new IllegalArgumentException( e ); entityManager().markForRollbackOnly();
throw new IllegalArgumentException( e.getMessage(), e );
} }
catch (HibernateException he) { catch (HibernateException he) {
throw entityManager.convert( he ); throw entityManager.convert( he );
@ -525,7 +527,8 @@ public abstract class BaseQueryImpl implements Query {
findParameterRegistration( param ).bindValue( value, temporalType ); findParameterRegistration( param ).bindValue( value, temporalType );
} }
catch (QueryParameterException e) { catch (QueryParameterException e) {
throw new IllegalArgumentException( e ); entityManager().markForRollbackOnly();
throw new IllegalArgumentException( e.getMessage(), e );
} }
catch (HibernateException he) { catch (HibernateException he) {
throw entityManager.convert( he ); throw entityManager.convert( he );
@ -543,7 +546,8 @@ public abstract class BaseQueryImpl implements Query {
findParameterRegistration( name ).bindValue( value ); findParameterRegistration( name ).bindValue( value );
} }
catch (QueryParameterException e) { catch (QueryParameterException e) {
throw new IllegalArgumentException( e ); entityManager().markForRollbackOnly();
throw new IllegalArgumentException( e.getMessage(), e );
} }
catch (HibernateException he) { catch (HibernateException he) {
throw entityManager.convert( he ); throw entityManager.convert( he );
@ -560,7 +564,8 @@ public abstract class BaseQueryImpl implements Query {
findParameterRegistration( name ).bindValue( value, temporalType ); findParameterRegistration( name ).bindValue( value, temporalType );
} }
catch (QueryParameterException e) { catch (QueryParameterException e) {
throw new IllegalArgumentException( e ); entityManager().markForRollbackOnly();
throw new IllegalArgumentException( e.getMessage(), e );
} }
catch (HibernateException he) { catch (HibernateException he) {
throw entityManager.convert( he ); throw entityManager.convert( he );
@ -577,7 +582,8 @@ public abstract class BaseQueryImpl implements Query {
findParameterRegistration( name ).bindValue( value, temporalType ); findParameterRegistration( name ).bindValue( value, temporalType );
} }
catch (QueryParameterException e) { catch (QueryParameterException e) {
throw new IllegalArgumentException( e ); entityManager().markForRollbackOnly();
throw new IllegalArgumentException( e.getMessage(), e );
} }
catch (HibernateException he) { catch (HibernateException he) {
throw entityManager.convert( he ); throw entityManager.convert( he );
@ -594,7 +600,8 @@ public abstract class BaseQueryImpl implements Query {
findParameterRegistration( position ).bindValue( value ); findParameterRegistration( position ).bindValue( value );
} }
catch (QueryParameterException e) { catch (QueryParameterException e) {
throw new IllegalArgumentException( e ); entityManager().markForRollbackOnly();
throw new IllegalArgumentException( e.getMessage(), e );
} }
catch (HibernateException he) { catch (HibernateException he) {
throw entityManager.convert( he ); throw entityManager.convert( he );
@ -611,7 +618,8 @@ public abstract class BaseQueryImpl implements Query {
findParameterRegistration( position ).bindValue( value, temporalType ); findParameterRegistration( position ).bindValue( value, temporalType );
} }
catch (QueryParameterException e) { catch (QueryParameterException e) {
throw new IllegalArgumentException( e ); entityManager().markForRollbackOnly();
throw new IllegalArgumentException( e.getMessage(), e );
} }
catch (HibernateException he) { catch (HibernateException he) {
throw entityManager.convert( he ); throw entityManager.convert( he );
@ -628,13 +636,16 @@ public abstract class BaseQueryImpl implements Query {
findParameterRegistration( position ).bindValue( value, temporalType ); findParameterRegistration( position ).bindValue( value, temporalType );
} }
catch (ParameterStrategyException e) { catch (ParameterStrategyException e) {
entityManager().markForRollbackOnly();
throw new IllegalArgumentException( "Invalid mix of named and positional parameters", e ); throw new IllegalArgumentException( "Invalid mix of named and positional parameters", e );
} }
catch (NoSuchParameterException e) { catch (NoSuchParameterException e) {
entityManager().markForRollbackOnly();
throw new IllegalArgumentException( e.getMessage(), e ); throw new IllegalArgumentException( e.getMessage(), e );
} }
catch (QueryParameterException e) { catch (QueryParameterException e) {
throw new IllegalArgumentException( e ); entityManager().markForRollbackOnly();
throw new IllegalArgumentException( e.getMessage(), e );
} }
catch (HibernateException he) { catch (HibernateException he) {
throw entityManager.convert( he ); throw entityManager.convert( he );

View File

@ -72,6 +72,11 @@ public interface HibernateEntityManagerImplementor extends HibernateEntityManage
*/ */
boolean isTransactionInProgress(); 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 * Handles marking for rollback and other such operations that need to occur depending on the type of
* exception being handled. * exception being handled.