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) {
if( ! isOpen() ) {
if ( markForRollbackIfClosed ) {
markAsRollback();
markForRollbackOnly();
}
throw new IllegalStateException( "EntityManager is closed" );
}

View File

@ -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 );
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 );
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

View File

@ -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

View File

@ -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 );

View File

@ -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.