HHH-9980 - Implement mark-for-rollback-only handling for JdbcResourceLocalTransactionCoordinatorImpl

This commit is contained in:
Steve Ebersole 2015-07-24 09:49:15 -05:00
parent f429a8cb28
commit 7556a22c2f
2 changed files with 43 additions and 0 deletions

View File

@ -10,6 +10,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.transaction.Status; import javax.transaction.Status;
import org.hibernate.TransactionException;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.transaction.spi.IsolationDelegate; import org.hibernate.engine.transaction.spi.IsolationDelegate;
import org.hibernate.engine.transaction.spi.TransactionObserver; import org.hibernate.engine.transaction.spi.TransactionObserver;
@ -185,6 +186,7 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
public class TransactionDriverControlImpl implements TransactionDriver { public class TransactionDriverControlImpl implements TransactionDriver {
private final JdbcResourceTransaction jdbcResourceTransaction; private final JdbcResourceTransaction jdbcResourceTransaction;
private boolean invalid; private boolean invalid;
private boolean rollbackOnly = false;
public TransactionDriverControlImpl(JdbcResourceTransaction jdbcResourceTransaction) { public TransactionDriverControlImpl(JdbcResourceTransaction jdbcResourceTransaction) {
super(); super();
@ -211,6 +213,10 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
@Override @Override
public void commit() { public void commit() {
if ( rollbackOnly ) {
throw new TransactionException( "Transaction was marked for rollback only; cannot commit" );
}
JdbcResourceLocalTransactionCoordinatorImpl.this.beforeCompletionCallback(); JdbcResourceLocalTransactionCoordinatorImpl.this.beforeCompletionCallback();
jdbcResourceTransaction.commit(); jdbcResourceTransaction.commit();
JdbcResourceLocalTransactionCoordinatorImpl.this.afterCompletionCallback( true ); JdbcResourceLocalTransactionCoordinatorImpl.this.afterCompletionCallback( true );
@ -229,7 +235,14 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
@Override @Override
public void markRollbackOnly() { public void markRollbackOnly() {
if ( log.isDebugEnabled() ) {
log.debug(
"JDBC transaction marked for rollback-only (exception provided for stack trace)",
new Exception( "exception just for purpose of providing stack trace" )
);
}
rollbackOnly = true;
} }
} }
} }

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.test.resource.transaction.jdbc; package org.hibernate.test.resource.transaction.jdbc;
import org.hibernate.TransactionException;
import org.hibernate.resource.transaction.TransactionCoordinator; import org.hibernate.resource.transaction.TransactionCoordinator;
import org.hibernate.resource.transaction.TransactionCoordinatorBuilder; import org.hibernate.resource.transaction.TransactionCoordinatorBuilder;
import org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl; import org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl;
@ -50,4 +51,33 @@ public class BasicJdbcTransactionTests {
assertEquals( 0, sync.getFailedCompletionCount() ); assertEquals( 0, sync.getFailedCompletionCount() );
} }
@Test
@SuppressWarnings("EmptyCatchBlock")
public void testMarkRollbackOnly() {
final TransactionCoordinatorOwnerTestingImpl owner = new TransactionCoordinatorOwnerTestingImpl();
final JdbcResourceLocalTransactionCoordinatorBuilderImpl transactionCoordinatorBuilder =
new JdbcResourceLocalTransactionCoordinatorBuilderImpl();
final TransactionCoordinator transactionCoordinator = transactionCoordinatorBuilder.buildTransactionCoordinator(
owner,
new TransactionCoordinatorBuilder.TransactionCoordinatorOptions() {
@Override
public boolean shouldAutoJoinTransaction() {
return false;
}
}
);
transactionCoordinator.getTransactionDriverControl().begin();
transactionCoordinator.getTransactionDriverControl().markRollbackOnly();
try {
transactionCoordinator.getTransactionDriverControl().commit();
}
catch (TransactionException expected) {
}
finally {
transactionCoordinator.getTransactionDriverControl().rollback();
}
}
} }