mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#1197 - Refactor how @Transactional methods internally managed
This commit is contained in:
@@ -25,32 +25,32 @@ import java.util.concurrent.Callable;
|
||||
*/
|
||||
public final class TxScope {
|
||||
|
||||
int profileId;
|
||||
private int profileId;
|
||||
|
||||
TxType type;
|
||||
private TxType type;
|
||||
|
||||
String serverName;
|
||||
private String serverName;
|
||||
|
||||
TxIsolation isolation;
|
||||
private TxIsolation isolation;
|
||||
|
||||
PersistBatch batch;
|
||||
private PersistBatch batch;
|
||||
|
||||
PersistBatch batchOnCascade;
|
||||
private PersistBatch batchOnCascade;
|
||||
|
||||
int batchSize;
|
||||
private int batchSize;
|
||||
|
||||
boolean skipGeneratedKeys;
|
||||
private boolean skipGeneratedKeys;
|
||||
|
||||
boolean readOnly;
|
||||
private boolean readOnly;
|
||||
|
||||
/**
|
||||
* Set this to false if the JDBC batch should not be automatically be flushed when a query is executed.
|
||||
*/
|
||||
boolean flushOnQuery = true;
|
||||
private boolean flushOnQuery = true;
|
||||
|
||||
ArrayList<Class<? extends Throwable>> rollbackFor;
|
||||
private ArrayList<Class<? extends Throwable>> rollbackFor;
|
||||
|
||||
ArrayList<Class<? extends Throwable>> noRollbackFor;
|
||||
private ArrayList<Class<? extends Throwable>> noRollbackFor;
|
||||
|
||||
/**
|
||||
* Helper method to create a TxScope with REQUIRES.
|
||||
@@ -275,6 +275,13 @@ public final class TxScope {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the isolation level.
|
||||
*/
|
||||
public int getIsolationLevel() {
|
||||
return isolation != null ? isolation.getLevel() : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Isolation level this transaction should run with.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.TxScope;
|
||||
|
||||
/**
|
||||
@@ -10,28 +9,20 @@ import io.ebean.TxScope;
|
||||
public class HelpScopeTrans {
|
||||
|
||||
/**
|
||||
* Create a ScopeTrans for a given methods TxScope.
|
||||
* Entering an enhanced transactional method.
|
||||
*/
|
||||
public static ScopeTrans createScopeTrans(TxScope txScope) {
|
||||
|
||||
EbeanServer server = Ebean.getServer(txScope.getServerName());
|
||||
SpiEbeanServer iserver = (SpiEbeanServer) server;
|
||||
return iserver.createScopeTrans(txScope);
|
||||
public static void enter(TxScope txScope) {
|
||||
server().scopedTransactionEnter(txScope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exiting the method in an expected fashion.
|
||||
* <p>
|
||||
* That is returning successfully or via a caught exception.
|
||||
* Unexpected exceptions are caught via the Thread uncaughtExceptionHandler.
|
||||
* </p>
|
||||
*
|
||||
* @param returnOrThrowable the return or throwable object
|
||||
* @param opCode the opcode for ATHROW or ARETURN etc
|
||||
* @param scopeTrans the scoped transaction the method was run with.
|
||||
* Exiting an enhanced transactional method.
|
||||
*/
|
||||
public static void onExitScopeTrans(Object returnOrThrowable, int opCode, ScopeTrans scopeTrans) {
|
||||
public static void exit(Object returnOrThrowable, int opCode) {
|
||||
server().scopedTransactionExit(returnOrThrowable, opCode);
|
||||
}
|
||||
|
||||
scopeTrans.onExit(returnOrThrowable, opCode);
|
||||
private static SpiEbeanServer server() {
|
||||
return (SpiEbeanServer) Ebean.getDefaultServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,17 +8,10 @@ import java.util.ArrayList;
|
||||
/**
|
||||
* Used internally to handle the scoping of transactions for methods.
|
||||
*/
|
||||
public class ScopeTrans implements Thread.UncaughtExceptionHandler {
|
||||
public class ScopeTrans {
|
||||
|
||||
private static final int OPCODE_ATHROW = 191;
|
||||
|
||||
private final SpiTransactionScopeManager scopeMgr;
|
||||
|
||||
/**
|
||||
* The suspended transaction (can be null).
|
||||
*/
|
||||
private final SpiTransaction suspendedTransaction;
|
||||
|
||||
/**
|
||||
* The transaction in scope (can be null).
|
||||
*/
|
||||
@@ -61,15 +54,11 @@ public class ScopeTrans implements Thread.UncaughtExceptionHandler {
|
||||
private boolean rolledBack;
|
||||
|
||||
|
||||
public ScopeTrans(boolean rollbackOnChecked, boolean created, SpiTransaction transaction, TxScope txScope,
|
||||
SpiTransaction suspendedTransaction, SpiTransactionScopeManager scopeMgr) {
|
||||
public ScopeTrans(boolean rollbackOnChecked, boolean created, SpiTransaction transaction, TxScope txScope) {
|
||||
|
||||
this.rollbackOnChecked = rollbackOnChecked;
|
||||
this.created = created;
|
||||
this.transaction = transaction;
|
||||
this.suspendedTransaction = suspendedTransaction;
|
||||
this.scopeMgr = scopeMgr;
|
||||
|
||||
this.noRollbackFor = txScope.getNoRollbackFor();
|
||||
this.rollbackFor = txScope.getRollbackFor();
|
||||
|
||||
@@ -108,55 +97,30 @@ public class ScopeTrans implements Thread.UncaughtExceptionHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the Thread catches any uncaught exception.
|
||||
* For example, an unexpected NullPointerException or Error.
|
||||
* Complete the transaction from enhanced transactional. Try to commit.
|
||||
*/
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable e) {
|
||||
|
||||
// rollback transaction if required
|
||||
caughtThrowable(e);
|
||||
|
||||
// reinstate suspended transaction
|
||||
onFinally();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returned via RETURN or expected Exception from the method.
|
||||
*
|
||||
* @param returnOrThrowable the return value or Throwable
|
||||
* @param opCode indicates
|
||||
*/
|
||||
public void onExit(Object returnOrThrowable, int opCode) {
|
||||
void complete(Object returnOrThrowable, int opCode) {
|
||||
|
||||
if (opCode == OPCODE_ATHROW) {
|
||||
// exited with a Throwable
|
||||
caughtThrowable((Throwable) returnOrThrowable);
|
||||
}
|
||||
onFinally();
|
||||
complete();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Commit if the transaction exists and has not already been rolled back.
|
||||
* Also reinstate the suspended transaction if there was one.
|
||||
* Complete the transaction programmatically. Try to commit.
|
||||
*/
|
||||
public void onFinally() {
|
||||
|
||||
try {
|
||||
if (!rolledBack) {
|
||||
commitTransaction();
|
||||
}
|
||||
} finally {
|
||||
restoreSuspended();
|
||||
public void complete() {
|
||||
if (!rolledBack) {
|
||||
commitTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
protected void restoreSuspended() {
|
||||
if (created || suspendedTransaction != null) {
|
||||
// put the previously suspended transaction
|
||||
// back onto the ThreadLocal or equivalent
|
||||
scopeMgr.replace(suspendedTransaction);
|
||||
public void end() {
|
||||
if (created) {
|
||||
transaction.end();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,17 +211,10 @@ public class ScopeTrans implements Thread.UncaughtExceptionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (e instanceof RuntimeException) {
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// checked exceptions...
|
||||
// EJB defaults this to false which is not intuitive IMO
|
||||
// Ebean makes this configurable (default to true)
|
||||
return rollbackOnChecked;
|
||||
}
|
||||
// checked exceptions...
|
||||
// EJB defaults this to false which is not intuitive IMO
|
||||
// Ebean makes this configurable (default to true)
|
||||
return e instanceof RuntimeException || rollbackOnChecked;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,432 +1,116 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.TransactionCallback;
|
||||
import io.ebean.annotation.DocStoreMode;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebean.event.changelog.BeanChange;
|
||||
import io.ebean.event.changelog.ChangeSet;
|
||||
import io.ebeaninternal.server.core.PersistDeferredRelationship;
|
||||
import io.ebeaninternal.server.core.PersistRequest;
|
||||
import io.ebeaninternal.server.core.PersistRequestBean;
|
||||
import io.ebeaninternal.server.persist.BatchControl;
|
||||
import io.ebeaninternal.server.transaction.ProfileStream;
|
||||
import io.ebeanservice.docstore.api.DocStoreTransaction;
|
||||
import io.ebeaninternal.server.transaction.TransactionScopeManager;
|
||||
import io.ebeaninternal.server.util.ArrayStack;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Wrapper of a ScopeTrans request and it's underlying transaction.
|
||||
* Manage scoped (typically thread local) transactions.
|
||||
*
|
||||
* These can be nested and internally they are pushed and popped from a stack.
|
||||
*/
|
||||
public class ScopedTransaction implements SpiTransaction {
|
||||
public class ScopedTransaction extends SpiTransactionProxy {
|
||||
|
||||
private final ScopeTrans scopeTrans;
|
||||
private final TransactionScopeManager manager;
|
||||
|
||||
private final SpiTransaction transaction;
|
||||
/**
|
||||
* Stack of 'nested' transactions.
|
||||
*/
|
||||
private ArrayStack<ScopeTrans> stack = new ArrayStack<>();
|
||||
|
||||
private boolean committed;
|
||||
private ScopeTrans current;
|
||||
|
||||
public ScopedTransaction(ScopeTrans scopeTrans) {
|
||||
this.scopeTrans = scopeTrans;
|
||||
this.transaction = scopeTrans.getTransaction();
|
||||
public ScopedTransaction(TransactionScopeManager manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceException translate(String message, SQLException cause) {
|
||||
return transaction.translate(message, cause);
|
||||
/**
|
||||
* Push the scope transaction.
|
||||
*/
|
||||
public void push(ScopeTrans scopeTrans) {
|
||||
|
||||
if (current != null) {
|
||||
stack.push(current);
|
||||
}
|
||||
current = scopeTrans;
|
||||
transaction = scopeTrans.getTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitAndContinue() {
|
||||
transaction.commitAndContinue();
|
||||
/**
|
||||
* Exiting an enhanced transactional method.
|
||||
*/
|
||||
public void complete(Object returnOrThrowable, int opCode) {
|
||||
current.complete(returnOrThrowable, opCode);
|
||||
pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
scopeTrans.commitTransaction();
|
||||
committed = true;
|
||||
/**
|
||||
* Programmatic complete - finally block, try to commit.
|
||||
*/
|
||||
public void complete() {
|
||||
current.complete();
|
||||
pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() throws PersistenceException {
|
||||
scopeTrans.rollback(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback(Throwable e) throws PersistenceException {
|
||||
scopeTrans.rollback(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRollbackOnly() {
|
||||
scopeTrans.setRollbackOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRollbackOnly() {
|
||||
return transaction.isRollbackOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() throws PersistenceException {
|
||||
try {
|
||||
if (!committed) {
|
||||
scopeTrans.rollback(null);
|
||||
}
|
||||
} finally {
|
||||
scopeTrans.restoreSuspended();
|
||||
private void pop() {
|
||||
if (!stack.isEmpty()) {
|
||||
current = stack.pop();
|
||||
} else {
|
||||
manager.set(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long profileOffset() {
|
||||
return transaction.profileOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void profileEvent(SpiProfileTransactionEvent event) {
|
||||
transaction.profileEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileStream profileStream() {
|
||||
return transaction.profileStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTenantId(Object tenantId) {
|
||||
transaction.setTenantId(tenantId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTenantId() {
|
||||
return transaction.getTenantId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocStoreTransaction getDocStoreTransaction() {
|
||||
return transaction.getDocStoreTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocStoreMode getDocStoreMode() {
|
||||
return transaction.getDocStoreMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocStoreMode(DocStoreMode mode) {
|
||||
transaction.setDocStoreMode(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDocStoreBatchSize() {
|
||||
return transaction.getDocStoreBatchSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocStoreBatchSize(int batchSize) {
|
||||
transaction.setDocStoreBatchSize(batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogPrefix() {
|
||||
return transaction.getLogPrefix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLogSql() {
|
||||
return transaction.isLogSql();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLogSummary() {
|
||||
return transaction.isLogSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSql(String msg) {
|
||||
transaction.logSql(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSummary(String msg) {
|
||||
transaction.logSummary(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkipCache(boolean skipCache) {
|
||||
transaction.setSkipCache(skipCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkipCache() {
|
||||
return transaction.isSkipCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBeanChange(BeanChange beanChange) {
|
||||
transaction.addBeanChange(beanChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChangeLog(ChangeSet changes) {
|
||||
transaction.sendChangeLog(changes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDeferred(PersistDeferredRelationship derived) {
|
||||
transaction.registerDeferred(derived);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDeleteBean(Integer hash) {
|
||||
transaction.registerDeleteBean(hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterDeleteBean(Integer hash) {
|
||||
transaction.unregisterDeleteBean(hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegisteredDeleteBean(Integer hash) {
|
||||
return transaction.isRegisteredDeleteBean(hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterBean(Object bean) {
|
||||
transaction.unregisterBean(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegisteredBean(Object bean) {
|
||||
return transaction.isRegisteredBean(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return transaction.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TransactionCallback callback) {
|
||||
transaction.register(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return transaction.isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
transaction.setReadOnly(readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return transaction.isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPersistCascade(boolean persistCascade) {
|
||||
transaction.setPersistCascade(persistCascade);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUpdateAllLoadedProperties(boolean updateAllLoaded) {
|
||||
transaction.setUpdateAllLoadedProperties(updateAllLoaded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isUpdateAllLoadedProperties() {
|
||||
return transaction.isUpdateAllLoadedProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchMode(boolean useBatch) {
|
||||
transaction.setBatchMode(useBatch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatch(PersistBatch persistBatchMode) {
|
||||
transaction.setBatch(persistBatchMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistBatch getBatch() {
|
||||
return transaction.getBatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchOnCascade(PersistBatch batchOnCascadeMode) {
|
||||
transaction.setBatchOnCascade(batchOnCascadeMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistBatch getBatchOnCascade() {
|
||||
return transaction.getBatchOnCascade();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchSize(int batchSize) {
|
||||
transaction.setBatchSize(batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return transaction.getBatchSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchGetGeneratedKeys(boolean getGeneratedKeys) {
|
||||
transaction.setBatchGetGeneratedKeys(getGeneratedKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getBatchGetGeneratedKeys() {
|
||||
return transaction.getBatchGetGeneratedKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchFlushOnMixed(boolean batchFlushOnMixed) {
|
||||
transaction.setBatchFlushOnMixed(batchFlushOnMixed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchFlushOnQuery(boolean batchFlushOnQuery) {
|
||||
transaction.setBatchFlushOnQuery(batchFlushOnQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBatchFlushOnQuery() {
|
||||
return transaction.isBatchFlushOnQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws PersistenceException {
|
||||
transaction.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatch() throws PersistenceException {
|
||||
flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() {
|
||||
return transaction.getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addModification(String tableName, boolean inserts, boolean updates, boolean deletes) {
|
||||
transaction.addModification(tableName, inserts, updates, deletes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putUserObject(String name, Object value) {
|
||||
transaction.putUserObject(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getUserObject(String name) {
|
||||
return transaction.getUserObject(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void depth(int diff) {
|
||||
transaction.depth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int depth() {
|
||||
return transaction.depth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExplicit() {
|
||||
return transaction.isExplicit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransactionEvent getEvent() {
|
||||
return transaction.getEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistCascade() {
|
||||
return transaction.isPersistCascade();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBatchThisRequest(PersistRequest.Type type) {
|
||||
return transaction.isBatchThisRequest(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatchControl getBatchControl() {
|
||||
return transaction.getBatchControl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchControl(BatchControl control) {
|
||||
transaction.setBatchControl(control);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return transaction.getPersistenceContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPersistenceContext(PersistenceContext context) {
|
||||
transaction.setPersistenceContext(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getInternalConnection() {
|
||||
return transaction.getInternalConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSaveAssocManyIntersection(String intersectionTable, String beanName) {
|
||||
return transaction.isSaveAssocManyIntersection(intersectionTable, beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkBatchEscalationOnCascade(PersistRequestBean<?> request) {
|
||||
return transaction.checkBatchEscalationOnCascade(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatchOnCascade() {
|
||||
transaction.flushBatchOnCascade();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatchOnRollback() {
|
||||
transaction.flushBatchOnRollback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markNotQueryOnly() {
|
||||
transaction.markNotQueryOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkBatchEscalationOnCollection() {
|
||||
transaction.checkBatchEscalationOnCollection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatchOnCollection() {
|
||||
transaction.flushBatchOnCollection();
|
||||
public void end() throws PersistenceException {
|
||||
current.end();
|
||||
pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
transaction.close();
|
||||
end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
current.commitTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() throws PersistenceException {
|
||||
current.rollback(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback(Throwable e) throws PersistenceException {
|
||||
current.rollback(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRollbackOnly() {
|
||||
current.setRollbackOnly();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current transaction.
|
||||
*/
|
||||
public SpiTransaction current() {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback for Error.
|
||||
*/
|
||||
public Error caughtError(Error e) {
|
||||
return current.caughtError(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe rollback based on TxScope rollback on settings.
|
||||
*/
|
||||
public Exception caughtThrowable(Exception e) {
|
||||
return current.caughtThrowable(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -125,11 +125,6 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
|
||||
*/
|
||||
SpiTransaction currentServerTransaction();
|
||||
|
||||
/**
|
||||
* Create a ScopeTrans for a method for the given scope definition.
|
||||
*/
|
||||
ScopeTrans createScopeTrans(TxScope txScope);
|
||||
|
||||
/**
|
||||
* Create a ServerTransaction for query purposes.
|
||||
*
|
||||
@@ -213,4 +208,15 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
|
||||
* Create DDL handler given the platform and configuration of the server.
|
||||
*/
|
||||
DdlHandler createDdlHandler();
|
||||
|
||||
/**
|
||||
* Start an enhanced transactional method.
|
||||
*/
|
||||
void scopedTransactionEnter(TxScope txScope);
|
||||
|
||||
/**
|
||||
* Handle the end of an enhanced Transactional method.
|
||||
*/
|
||||
void scopedTransactionExit(Object returnOrThrowable, int opCode);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebean.TransactionCallback;
|
||||
import io.ebean.annotation.DocStoreMode;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebean.event.changelog.BeanChange;
|
||||
import io.ebean.event.changelog.ChangeSet;
|
||||
import io.ebeaninternal.server.core.PersistDeferredRelationship;
|
||||
import io.ebeaninternal.server.core.PersistRequest;
|
||||
import io.ebeaninternal.server.core.PersistRequestBean;
|
||||
import io.ebeaninternal.server.persist.BatchControl;
|
||||
import io.ebeaninternal.server.transaction.ProfileStream;
|
||||
import io.ebeanservice.docstore.api.DocStoreTransaction;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Proxy for an underlying SpiTransaction (most of the API).
|
||||
*/
|
||||
abstract class SpiTransactionProxy implements SpiTransaction {
|
||||
|
||||
protected SpiTransaction transaction;
|
||||
|
||||
@Override
|
||||
public PersistenceException translate(String message, SQLException cause) {
|
||||
return transaction.translate(message, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitAndContinue() {
|
||||
transaction.commitAndContinue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRollbackOnly() {
|
||||
return transaction.isRollbackOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long profileOffset() {
|
||||
return transaction.profileOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void profileEvent(SpiProfileTransactionEvent event) {
|
||||
transaction.profileEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileStream profileStream() {
|
||||
return transaction.profileStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTenantId(Object tenantId) {
|
||||
transaction.setTenantId(tenantId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTenantId() {
|
||||
return transaction.getTenantId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocStoreTransaction getDocStoreTransaction() {
|
||||
return transaction.getDocStoreTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocStoreMode getDocStoreMode() {
|
||||
return transaction.getDocStoreMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocStoreMode(DocStoreMode mode) {
|
||||
transaction.setDocStoreMode(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDocStoreBatchSize() {
|
||||
return transaction.getDocStoreBatchSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocStoreBatchSize(int batchSize) {
|
||||
transaction.setDocStoreBatchSize(batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogPrefix() {
|
||||
return transaction.getLogPrefix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLogSql() {
|
||||
return transaction.isLogSql();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLogSummary() {
|
||||
return transaction.isLogSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSql(String msg) {
|
||||
transaction.logSql(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSummary(String msg) {
|
||||
transaction.logSummary(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkipCache(boolean skipCache) {
|
||||
transaction.setSkipCache(skipCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkipCache() {
|
||||
return transaction.isSkipCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBeanChange(BeanChange beanChange) {
|
||||
transaction.addBeanChange(beanChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChangeLog(ChangeSet changes) {
|
||||
transaction.sendChangeLog(changes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDeferred(PersistDeferredRelationship derived) {
|
||||
transaction.registerDeferred(derived);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDeleteBean(Integer hash) {
|
||||
transaction.registerDeleteBean(hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterDeleteBean(Integer hash) {
|
||||
transaction.unregisterDeleteBean(hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegisteredDeleteBean(Integer hash) {
|
||||
return transaction.isRegisteredDeleteBean(hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterBean(Object bean) {
|
||||
transaction.unregisterBean(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegisteredBean(Object bean) {
|
||||
return transaction.isRegisteredBean(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return transaction.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TransactionCallback callback) {
|
||||
transaction.register(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return transaction.isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
transaction.setReadOnly(readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return transaction.isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPersistCascade(boolean persistCascade) {
|
||||
transaction.setPersistCascade(persistCascade);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUpdateAllLoadedProperties(boolean updateAllLoaded) {
|
||||
transaction.setUpdateAllLoadedProperties(updateAllLoaded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isUpdateAllLoadedProperties() {
|
||||
return transaction.isUpdateAllLoadedProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchMode(boolean useBatch) {
|
||||
transaction.setBatchMode(useBatch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatch(PersistBatch persistBatchMode) {
|
||||
transaction.setBatch(persistBatchMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistBatch getBatch() {
|
||||
return transaction.getBatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchOnCascade(PersistBatch batchOnCascadeMode) {
|
||||
transaction.setBatchOnCascade(batchOnCascadeMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistBatch getBatchOnCascade() {
|
||||
return transaction.getBatchOnCascade();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchSize(int batchSize) {
|
||||
transaction.setBatchSize(batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return transaction.getBatchSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchGetGeneratedKeys(boolean getGeneratedKeys) {
|
||||
transaction.setBatchGetGeneratedKeys(getGeneratedKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getBatchGetGeneratedKeys() {
|
||||
return transaction.getBatchGetGeneratedKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchFlushOnMixed(boolean batchFlushOnMixed) {
|
||||
transaction.setBatchFlushOnMixed(batchFlushOnMixed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchFlushOnQuery(boolean batchFlushOnQuery) {
|
||||
transaction.setBatchFlushOnQuery(batchFlushOnQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBatchFlushOnQuery() {
|
||||
return transaction.isBatchFlushOnQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws PersistenceException {
|
||||
transaction.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatch() throws PersistenceException {
|
||||
flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() {
|
||||
return transaction.getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addModification(String tableName, boolean inserts, boolean updates, boolean deletes) {
|
||||
transaction.addModification(tableName, inserts, updates, deletes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putUserObject(String name, Object value) {
|
||||
transaction.putUserObject(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getUserObject(String name) {
|
||||
return transaction.getUserObject(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void depth(int diff) {
|
||||
transaction.depth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int depth() {
|
||||
return transaction.depth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExplicit() {
|
||||
return transaction.isExplicit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransactionEvent getEvent() {
|
||||
return transaction.getEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistCascade() {
|
||||
return transaction.isPersistCascade();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBatchThisRequest(PersistRequest.Type type) {
|
||||
return transaction.isBatchThisRequest(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatchControl getBatchControl() {
|
||||
return transaction.getBatchControl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchControl(BatchControl control) {
|
||||
transaction.setBatchControl(control);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return transaction.getPersistenceContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPersistenceContext(PersistenceContext context) {
|
||||
transaction.setPersistenceContext(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getInternalConnection() {
|
||||
return transaction.getInternalConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSaveAssocManyIntersection(String intersectionTable, String beanName) {
|
||||
return transaction.isSaveAssocManyIntersection(intersectionTable, beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkBatchEscalationOnCascade(PersistRequestBean<?> request) {
|
||||
return transaction.checkBatchEscalationOnCascade(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatchOnCascade() {
|
||||
transaction.flushBatchOnCascade();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatchOnRollback() {
|
||||
transaction.flushBatchOnRollback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markNotQueryOnly() {
|
||||
transaction.markNotQueryOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkBatchEscalationOnCollection() {
|
||||
transaction.checkBatchEscalationOnCollection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatchOnCollection() {
|
||||
transaction.flushBatchOnCollection();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -659,7 +659,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
public Transaction createTransaction() {
|
||||
|
||||
return transactionManager.createTransaction(0,true, -1);
|
||||
return transactionManager.createTransaction(0, true, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -671,7 +671,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
public Transaction createTransaction(TxIsolation isolation) {
|
||||
|
||||
return transactionManager.createTransaction(0,true, isolation.getLevel());
|
||||
return transactionManager.createTransaction(0, true, isolation.getLevel());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -681,7 +681,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> T executeCall(TxScope scope, Callable<T> c) {
|
||||
ScopeTrans scopeTrans = createScopeTrans(scope);
|
||||
ScopedTransaction scopeTrans = scopedTransaction(scope);
|
||||
try {
|
||||
return c.call();
|
||||
|
||||
@@ -692,7 +692,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
throw new PersistenceException(scopeTrans.caughtThrowable(e));
|
||||
|
||||
} finally {
|
||||
scopeTrans.onFinally();
|
||||
scopeTrans.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,18 +703,18 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public void execute(TxScope scope, Runnable r) {
|
||||
ScopeTrans scopeTrans = createScopeTrans(scope);
|
||||
ScopedTransaction t = scopedTransaction(scope);
|
||||
try {
|
||||
r.run();
|
||||
|
||||
} catch (Error e) {
|
||||
throw scopeTrans.caughtError(e);
|
||||
throw t.caughtError(e);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new PersistenceException(scopeTrans.caughtThrowable(e));
|
||||
throw new PersistenceException(t.caughtThrowable(e));
|
||||
|
||||
} finally {
|
||||
scopeTrans.onFinally();
|
||||
t.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -758,51 +758,14 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScopeTrans createScopeTrans(TxScope txScope) {
|
||||
public void scopedTransactionEnter(TxScope txScope) {
|
||||
beginTransaction(txScope);
|
||||
}
|
||||
|
||||
if (txScope == null) {
|
||||
// create a TxScope with default settings
|
||||
txScope = new TxScope();
|
||||
} else {
|
||||
// check for implied batch mode via setting batchSize
|
||||
txScope.checkBatchMode();
|
||||
}
|
||||
|
||||
SpiTransaction suspended = null;
|
||||
|
||||
// get current transaction from ThreadLocal or equivalent
|
||||
SpiTransaction t = transactionScopeManager.get();
|
||||
|
||||
boolean newTransaction;
|
||||
if (txScope.getType().equals(TxType.NOT_SUPPORTED)) {
|
||||
// Suspend existing transaction and
|
||||
// run without a transaction in scope
|
||||
newTransaction = false;
|
||||
suspended = t;
|
||||
t = null;
|
||||
transactionScopeManager.replace(null);
|
||||
|
||||
} else {
|
||||
// create a new Transaction based on TxType and t
|
||||
newTransaction = createNewTransaction(t, txScope);
|
||||
|
||||
if (newTransaction) {
|
||||
// suspend existing transaction (if there is one)
|
||||
suspended = t;
|
||||
|
||||
// create a new transaction
|
||||
int isoLevel = -1;
|
||||
TxIsolation isolation = txScope.getIsolation();
|
||||
if (isolation != null) {
|
||||
isoLevel = isolation.getLevel();
|
||||
}
|
||||
t = transactionManager.createTransaction(txScope.getProfileId(), true, isoLevel);
|
||||
// note ScopeTrans.onFinally() restores the suspended transaction
|
||||
transactionScopeManager.replace(t);
|
||||
}
|
||||
}
|
||||
|
||||
return new ScopeTrans(rollbackOnChecked, newTransaction, t, txScope, suspended, transactionScopeManager);
|
||||
@Override
|
||||
public void scopedTransactionExit(Object returnOrThrowable, int opCode) {
|
||||
ScopedTransaction st = (ScopedTransaction) transactionScopeManager.getScoped();
|
||||
st.complete(returnOrThrowable, opCode);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -828,9 +791,52 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transaction beginTransaction(TxScope scope) {
|
||||
ScopeTrans scopeTrans = createScopeTrans(scope);
|
||||
return new ScopedTransaction(scopeTrans);
|
||||
public Transaction beginTransaction(TxScope txScope) {
|
||||
return scopedTransaction(txScope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Scoped transaction which internally can 'nest' transactions on it's own stack.
|
||||
*/
|
||||
ScopedTransaction scopedTransaction(TxScope txScope) {
|
||||
|
||||
txScope = initTxScope(txScope);
|
||||
|
||||
boolean setToScope = false;
|
||||
ScopedTransaction txnContainer = (ScopedTransaction) transactionScopeManager.get();
|
||||
if (txnContainer == null) {
|
||||
setToScope = true;
|
||||
txnContainer = new ScopedTransaction(transactionScopeManager);
|
||||
}
|
||||
|
||||
SpiTransaction transaction = txnContainer.current();
|
||||
|
||||
boolean createTransaction;
|
||||
if (txScope.getType() == TxType.NOT_SUPPORTED) {
|
||||
createTransaction = false;
|
||||
transaction = null;
|
||||
} else {
|
||||
createTransaction = createNewTransaction(transaction, txScope);
|
||||
if (createTransaction) {
|
||||
transaction = transactionManager.createTransaction(txScope.getProfileId(), true, txScope.getIsolationLevel());
|
||||
}
|
||||
}
|
||||
|
||||
txnContainer.push(new ScopeTrans(rollbackOnChecked, createTransaction, transaction, txScope));
|
||||
if (setToScope) {
|
||||
transactionScopeManager.set(txnContainer);
|
||||
}
|
||||
return txnContainer;
|
||||
}
|
||||
|
||||
private TxScope initTxScope(TxScope txScope) {
|
||||
if (txScope == null) {
|
||||
return new TxScope();
|
||||
} else {
|
||||
// check for implied batch mode via setting batchSize
|
||||
txScope.checkBatchMode();
|
||||
return txScope;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -842,7 +848,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
public Transaction beginTransaction(TxIsolation isolation) {
|
||||
// start an explicit transaction
|
||||
SpiTransaction t = transactionManager.createTransaction(0,true, isolation.getLevel());
|
||||
SpiTransaction t = transactionManager.createTransaction(0, true, isolation.getLevel());
|
||||
try {
|
||||
transactionScopeManager.set(t);
|
||||
} catch (PersistenceException existingTransactionError) {
|
||||
@@ -1717,7 +1723,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
public <T> List<T> draftRestore(Query<T> query, Transaction transaction) {
|
||||
|
||||
return executeInTrans((txn)-> persister.draftRestore(query, txn), transaction);
|
||||
return executeInTrans((txn) -> persister.draftRestore(query, txn), transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2063,7 +2069,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
transactionManager.remoteTransactionEvent(event);
|
||||
}
|
||||
|
||||
private <P> P executeInTrans(Function<SpiTransaction,P> fun, Transaction t) {
|
||||
private <P> P executeInTrans(Function<SpiTransaction, P> fun, Transaction t) {
|
||||
ObtainedTransaction wrap = initTransIfRequired(t);
|
||||
try {
|
||||
P result = fun.apply(wrap.transaction());
|
||||
@@ -2094,7 +2100,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public SpiTransaction beginServerTransaction() {
|
||||
SpiTransaction t = transactionManager.createTransaction(0,false, -1);
|
||||
SpiTransaction t = transactionManager.createTransaction(0, false, -1);
|
||||
transactionScopeManager.set(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ public class DefaultTransactionScopeManager extends TransactionScopeManager {
|
||||
DefaultTransactionThreadLocal.end(serverName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction getScoped() {
|
||||
return DefaultTransactionThreadLocal.get(serverName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction get() {
|
||||
SpiTransaction t = DefaultTransactionThreadLocal.get(serverName);
|
||||
|
||||
+5
-1
@@ -32,8 +32,12 @@ public class ExternalTransactionScopeManager extends TransactionScopeManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction get() {
|
||||
public SpiTransaction getScoped() {
|
||||
return get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction get() {
|
||||
return (SpiTransaction) externalManager.getCurrentTransaction();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,11 @@ public abstract class TransactionScopeManager implements SpiTransactionScopeMana
|
||||
this.serverName = transactionManager.getServerName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current Transaction allowing it to be inactive.
|
||||
*/
|
||||
public abstract SpiTransaction getScoped();
|
||||
|
||||
/**
|
||||
* Return the current Transaction for this serverName and Thread.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user