#1245 - Refactor internals - move logic to TransactionManager from DefaultServer

This commit is contained in:
Rob Bygrave committed 2018-01-31 11:56:38 +13:00
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?");
}
}
}