HHH-9993 IsolationDelegate: add method to execute code without obtaining a connection
This commit is contained in:
parent
2167b442a4
commit
aaf13cd123
|
@ -9,6 +9,8 @@ package org.hibernate.engine.transaction.spi;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.jdbc.WorkExecutorVisitable;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Contract for performing work in a manner that isolates it from any current transaction.
|
||||
*
|
||||
|
@ -26,4 +28,16 @@ public interface IsolationDelegate {
|
|||
* @throws HibernateException Indicates a problem performing the work.
|
||||
*/
|
||||
public <T> T delegateWork(WorkExecutorVisitable<T> work, boolean transacted) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Invoke the given callable in isolation from current transaction.
|
||||
*
|
||||
* @param callable The callable to be invoked.
|
||||
* @param transacted Should the work itself be done in a (isolated) transaction?
|
||||
*
|
||||
* @return The work result
|
||||
*
|
||||
* @throws HibernateException Indicates a problem performing the work.
|
||||
*/
|
||||
public <T> T delegateCallable(Callable<T> callable, boolean transacted) throws HibernateException;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.resource.transaction.backend.jdbc.internal;
|
|||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
|
@ -102,4 +103,18 @@ public class JdbcIsolationDelegate implements IsolationDelegate {
|
|||
throw sqlExceptionHelper().convert( sqle, "unable to obtain isolated JDBC connection" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T delegateCallable(Callable<T> callable, boolean transacted) throws HibernateException {
|
||||
// No connection, nothing to be suspended
|
||||
try {
|
||||
return callable.call();
|
||||
}
|
||||
catch (HibernateException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import javax.transaction.Transaction;
|
|||
import javax.transaction.TransactionManager;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
|
@ -52,7 +53,56 @@ public class JtaIsolationDelegate implements IsolationDelegate {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> T delegateWork(WorkExecutorVisitable<T> work, boolean transacted) throws HibernateException {
|
||||
public <T> T delegateWork(final WorkExecutorVisitable<T> work, final boolean transacted) throws HibernateException {
|
||||
return doInSuspendedTransaction(new HibernateCallable<T>() {
|
||||
@Override
|
||||
public T call() throws HibernateException {
|
||||
HibernateCallable<T> workCallable = new HibernateCallable<T>() {
|
||||
@Override
|
||||
public T call() throws HibernateException {
|
||||
return doTheWork(work);
|
||||
}
|
||||
};
|
||||
if ( transacted ) {
|
||||
return doInNewTransaction( workCallable, transactionManager );
|
||||
}
|
||||
else {
|
||||
return workCallable.call();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T delegateCallable(final Callable<T> callable, final boolean transacted) throws HibernateException {
|
||||
return doInSuspendedTransaction(new HibernateCallable<T>() {
|
||||
@Override
|
||||
public T call() throws HibernateException {
|
||||
HibernateCallable<T> workCallable = new HibernateCallable<T>() {
|
||||
@Override
|
||||
public T call() throws HibernateException {
|
||||
try {
|
||||
return callable.call();
|
||||
}
|
||||
catch (HibernateException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
if ( transacted ) {
|
||||
return doInNewTransaction( workCallable, transactionManager );
|
||||
}
|
||||
else {
|
||||
return workCallable.call();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private <T> T doInSuspendedTransaction(HibernateCallable<T> callable) {
|
||||
try {
|
||||
// First we suspend any current JTA transaction
|
||||
Transaction surroundingTransaction = transactionManager.suspend();
|
||||
|
@ -60,13 +110,7 @@ public class JtaIsolationDelegate implements IsolationDelegate {
|
|||
|
||||
boolean hadProblems = false;
|
||||
try {
|
||||
// then perform the requested work
|
||||
if ( transacted ) {
|
||||
return doTheWorkInNewTransaction( work, transactionManager );
|
||||
}
|
||||
else {
|
||||
return doTheWorkInNoTransaction( work );
|
||||
}
|
||||
return callable.call();
|
||||
}
|
||||
catch (HibernateException e) {
|
||||
hadProblems = true;
|
||||
|
@ -91,13 +135,13 @@ public class JtaIsolationDelegate implements IsolationDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
private <T> T doTheWorkInNewTransaction(WorkExecutorVisitable<T> work, TransactionManager transactionManager) {
|
||||
private <T> T doInNewTransaction(HibernateCallable<T> callable, TransactionManager transactionManager) {
|
||||
try {
|
||||
// start the new isolated transaction
|
||||
transactionManager.begin();
|
||||
|
||||
try {
|
||||
T result = doTheWork( work );
|
||||
T result = callable.call();
|
||||
// if everything went ok, commit the isolated transaction
|
||||
transactionManager.commit();
|
||||
return result;
|
||||
|
@ -120,10 +164,6 @@ public class JtaIsolationDelegate implements IsolationDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
private <T> T doTheWorkInNoTransaction(WorkExecutorVisitable<T> work) {
|
||||
return doTheWork( work );
|
||||
}
|
||||
|
||||
private <T> T doTheWork(WorkExecutorVisitable<T> work) {
|
||||
try {
|
||||
// obtain our isolated connection
|
||||
|
@ -152,4 +192,9 @@ public class JtaIsolationDelegate implements IsolationDelegate {
|
|||
throw sqlExceptionHelper().convert( e, "unable to obtain isolated JDBC connection" );
|
||||
}
|
||||
}
|
||||
|
||||
// Callable that does not throw Exception; in Java <8 there's no Supplier
|
||||
private interface HibernateCallable<T> {
|
||||
T call() throws HibernateException;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue