mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-11-12 14:40:46 +00:00
#1245 - Refactor internals - move logic to TransactionManager from DefaultServer
This commit is contained in:
1 parent
5bd7853ce8
commit
b682293a32
3 files changed
+133
-123
No files matched your search
@@ -0,0 +1,442 @@
|
||||
package io.ebeaninternal.server.transaction;
|
||||
|
||||
import io.ebean.ProfileLocation;
|
||||
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.api.SpiProfileTransactionEvent;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import io.ebeaninternal.api.TransactionEvent;
|
||||
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.ebeanservice.docstore.api.DocStoreTransaction;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Place holder for use with SUPPORTS and NEVER transactional when there really isn't a transaction.
|
||||
*/
|
||||
class NoTransaction implements SpiTransaction {
|
||||
|
||||
static final NoTransaction INSTANCE = new NoTransaction();
|
||||
|
||||
@Override
|
||||
public void setLabel(String label) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
// always false
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitAndContinue() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() throws PersistenceException {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void rollback(Throwable e) throws PersistenceException {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogPrefix() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLogSql() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLogSummary() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSql(String msg) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSummary(String msg) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDeferred(PersistDeferredRelationship derived) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDeleteBean(Integer hash) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterDeleteBean(Integer hash) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegisteredDeleteBean(Integer hash) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterBean(Object bean) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegisteredBean(Object bean) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isUpdateAllLoadedProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocStoreMode getDocStoreMode() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDocStoreBatchSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(TransactionCallback callback) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRollbackOnly() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRollbackOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setDocStoreMode(DocStoreMode mode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocStoreBatchSize(int batchSize) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPersistCascade(boolean persistCascade) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUpdateAllLoadedProperties(boolean updateAllLoadedProperties) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkipCache(boolean skipCache) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkipCache() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchMode(boolean useBatch) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatch(PersistBatch persistBatchMode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistBatch getBatch() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchOnCascade(PersistBatch batchOnCascadeMode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistBatch getBatchOnCascade() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchSize(int batchSize) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchGetGeneratedKeys(boolean getGeneratedKeys) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchFlushOnMixed(boolean batchFlushOnMixed) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchFlushOnQuery(boolean batchFlushOnQuery) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBatchFlushOnQuery() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws PersistenceException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatch() throws PersistenceException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addModification(String tableName, boolean inserts, boolean updates, boolean deletes) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putUserObject(String name, Object value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getUserObject(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getBatchGetGeneratedKeys() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void depth(int diff) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int depth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExplicit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransactionEvent getEvent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistCascade() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBatchThisRequest(PersistRequest.Type type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatchControl getBatchControl() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchControl(BatchControl control) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPersistenceContext(PersistenceContext context) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getInternalConnection() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSaveAssocManyIntersection(String intersectionTable, String beanName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkBatchEscalationOnCascade(PersistRequestBean<?> request) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatchOnCascade() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatchOnRollback() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceException translate(String message, SQLException cause) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markNotQueryOnly() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkBatchEscalationOnCollection() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatchOnCollection() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBeanChange(BeanChange beanChange) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChangeLog(ChangeSet changeSet) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocStoreTransaction getDocStoreTransaction() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTenantId(Object tenantId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTenantId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long profileOffset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void profileEvent(SpiProfileTransactionEvent event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileStream profileStream() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProfileLocation(ProfileLocation profileLocation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileLocation getProfileLocation() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
package io.ebeaninternal.server.transaction;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.ProfileLocation;
|
||||
import io.ebean.TxScope;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.annotation.TxType;
|
||||
import io.ebean.config.CurrentTenantProvider;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform.OnQueryOnly;
|
||||
@@ -9,6 +12,7 @@ import io.ebean.event.changelog.ChangeLogListener;
|
||||
import io.ebean.event.changelog.ChangeLogPrepare;
|
||||
import io.ebean.event.changelog.ChangeSet;
|
||||
import io.ebean.meta.MetaTimedMetric;
|
||||
import io.ebeaninternal.api.ScopeTrans;
|
||||
import io.ebeaninternal.api.ScopedTransaction;
|
||||
import io.ebeaninternal.api.SpiProfileHandler;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
@@ -56,6 +60,12 @@ public class TransactionManager {
|
||||
|
||||
protected final BeanDescriptorManager beanDescriptorManager;
|
||||
|
||||
/**
|
||||
* Ebean defaults this to true but for EJB compatible behaviour set this to
|
||||
* false;
|
||||
*/
|
||||
private final boolean rollbackOnChecked;
|
||||
|
||||
/**
|
||||
* Prefix for transaction id's (logging).
|
||||
*/
|
||||
@@ -137,6 +147,7 @@ public class TransactionManager {
|
||||
this.localL2Caching = options.localL2Caching;
|
||||
this.persistBatch = options.config.getPersistBatch();
|
||||
this.persistBatchOnCascade = options.config.appliedPersistBatchOnCascade();
|
||||
this.rollbackOnChecked = options.config.isTransactionRollbackOnChecked();
|
||||
this.beanDescriptorManager = options.descMgr;
|
||||
this.viewInvalidation = options.descMgr.requiresViewEntityCacheInvalidation();
|
||||
this.changeLogPrepare = options.descMgr.getChangeLogPrepare();
|
||||
@@ -203,7 +214,7 @@ public class TransactionManager {
|
||||
/**
|
||||
* Return the current scoped transaction allowing it to be inactive (already committed or rolled back).
|
||||
*/
|
||||
public ScopedTransaction getMaybeInactive() {
|
||||
private ScopedTransaction getMaybeInactive() {
|
||||
return (ScopedTransaction)scopeManager.getMaybeInactive();
|
||||
}
|
||||
|
||||
@@ -534,4 +545,117 @@ public class TransactionManager {
|
||||
scopeManager.set(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit a scoped transaction (that can be inactive - already committed etc).
|
||||
*/
|
||||
public void exitScopedTransaction(Object returnOrThrowable, int opCode) {
|
||||
ScopedTransaction st = getMaybeInactive();
|
||||
if (st != null) {
|
||||
// can be null for Supports as that can start as a 'No Transaction' and then
|
||||
// effectively be replaced by transactions inside the scope
|
||||
st.complete(returnOrThrowable, opCode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin a scoped transaction.
|
||||
*/
|
||||
public ScopedTransaction beginScopedTransaction(TxScope txScope) {
|
||||
|
||||
txScope = initTxScope(txScope);
|
||||
|
||||
boolean setToScope = false;
|
||||
ScopedTransaction txnContainer = getScoped();
|
||||
if (txnContainer == null) {
|
||||
setToScope = true;
|
||||
txnContainer = createScopedTransaction();
|
||||
}
|
||||
|
||||
SpiTransaction transaction = txnContainer.current();
|
||||
|
||||
TxType type = txScope.getType();
|
||||
boolean createTransaction = isCreateNewTransaction(transaction, type);
|
||||
if (createTransaction) {
|
||||
switch (type) {
|
||||
case SUPPORTS:
|
||||
case NOT_SUPPORTED:
|
||||
case NEVER:
|
||||
transaction = NoTransaction.INSTANCE;
|
||||
break;
|
||||
default:
|
||||
transaction = createTransaction(txScope.getProfileId(), true, txScope.getIsolationLevel());
|
||||
initNewTransaction(transaction, txScope);
|
||||
}
|
||||
}
|
||||
|
||||
txnContainer.push(new ScopeTrans(rollbackOnChecked, createTransaction, transaction, txScope));
|
||||
if (setToScope) {
|
||||
set(txnContainer);
|
||||
}
|
||||
return txnContainer;
|
||||
}
|
||||
|
||||
private void initNewTransaction(SpiTransaction transaction, TxScope txScope) {
|
||||
|
||||
if (txScope.isSkipCache()) {
|
||||
transaction.setSkipCache(true);
|
||||
}
|
||||
String label = txScope.getLabel();
|
||||
if (label != null) {
|
||||
transaction.setLabel(label);
|
||||
}
|
||||
ProfileLocation profileLocation = txScope.getProfileLocation();
|
||||
if (profileLocation != null) {
|
||||
profileLocation.obtain();
|
||||
transaction.setProfileLocation(profileLocation);
|
||||
}
|
||||
}
|
||||
|
||||
private TxScope initTxScope(TxScope txScope) {
|
||||
if (txScope == null) {
|
||||
return new TxScope();
|
||||
} else {
|
||||
// check for implied batch mode via setting batchSize
|
||||
txScope.checkBatchMode();
|
||||
return txScope;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether to create a new transaction or not.
|
||||
* <p>
|
||||
* This will also potentially throw exceptions for MANDATORY and NEVER types.
|
||||
* </p>
|
||||
*/
|
||||
private boolean isCreateNewTransaction(SpiTransaction current, TxType type) {
|
||||
switch (type) {
|
||||
case REQUIRED:
|
||||
return current == null;
|
||||
|
||||
case REQUIRES_NEW:
|
||||
return true;
|
||||
|
||||
case MANDATORY:
|
||||
if (current == null) {
|
||||
throw new PersistenceException("Transaction missing when MANDATORY");
|
||||
}
|
||||
return false;
|
||||
|
||||
case SUPPORTS:
|
||||
return current == null;
|
||||
|
||||
case NEVER:
|
||||
if (current != null) {
|
||||
throw new PersistenceException("Transaction exists for Transactional NEVER");
|
||||
}
|
||||
return true; // always use NoTransaction instance
|
||||
|
||||
case NOT_SUPPORTED:
|
||||
return true; // always use NoTransaction instance
|
||||
|
||||
default:
|
||||
throw new RuntimeException("Should never get here?");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user