#1770 - Support use of Savepoints with MySql and MariaDB (that barf on savepoint.getSavepointId())

This commit is contained in:
rob bygrave
2019-07-21 22:57:56 +12:00
parent f12f0d7f7a
commit a08cf548e7
10 changed files with 54 additions and 22 deletions
@@ -51,6 +51,8 @@ public class DatabasePlatform {
protected boolean supportsDeleteTableAlias;
protected boolean supportsSavepointId = true;
/**
* The behaviour used when ending a read only transaction at read committed isolation level.
*/
@@ -328,6 +330,13 @@ public class DatabasePlatform {
return caseSensitiveCollation;
}
/**
* Return true if the platform supports SavepointId values.
*/
public boolean isSupportsSavepointId() {
return supportsSavepointId;
}
/**
* Return the maximum table name length.
* <p>
@@ -27,6 +27,7 @@ public class MySqlPlatform extends DatabasePlatform {
this.platform = Platform.MYSQL;
this.useExtraTransactionOnIterateSecondaryQueries = true;
this.selectCountWithAlias = true;
this.supportsSavepointId = false;
this.dbEncrypt = new MySqlDbEncrypt();
this.historySupport = new MySqlHistorySupport();
this.columnAliasPrefix = null;
@@ -19,9 +19,8 @@ public class AutoCommitTransactionManager extends TransactionManager {
* Create an autoCommit based Transaction.
*/
@Override
protected SpiTransaction createTransaction(boolean explicit, Connection c, long id) {
return new AutoCommitJdbcTransaction(prefix + id, explicit, c, this);
protected SpiTransaction createTransaction(boolean explicit, Connection c) {
return new AutoCommitJdbcTransaction(nextTxnId(), explicit, c, this);
}
}
@@ -3,7 +3,6 @@ package io.ebeaninternal.server.transaction;
import io.ebeaninternal.api.SpiTransaction;
import java.sql.Connection;
import java.util.concurrent.atomic.AtomicLong;
/**
* Transaction manager used for doc store only EbeanServer instance.
@@ -12,8 +11,6 @@ import java.util.concurrent.atomic.AtomicLong;
*/
public class DocStoreTransactionManager extends TransactionManager {
private final AtomicLong counter = new AtomicLong(1000L);
/**
* Create the TransactionManager
*/
@@ -23,8 +20,7 @@ public class DocStoreTransactionManager extends TransactionManager {
@Override
public SpiTransaction createTransaction(boolean explicit, int isolationLevel) {
long id = counter.incrementAndGet();
return createTransaction(explicit, null, id);
return createTransaction(explicit, null);
}
@Override
@@ -33,7 +29,7 @@ public class DocStoreTransactionManager extends TransactionManager {
}
@Override
protected SpiTransaction createTransaction(boolean explicit, Connection c, long id) {
return new DocStoreOnlyTransaction(prefix + id, explicit, this);
protected SpiTransaction createTransaction(boolean explicit, Connection c) {
return new DocStoreOnlyTransaction(nextTxnId(), explicit, this);
}
}
@@ -18,9 +18,8 @@ public class ExplicitTransactionManager extends TransactionManager {
* Create a ExplicitJdbcTransaction.
*/
@Override
protected SpiTransaction createTransaction(boolean explicit, Connection c, long id) {
return new ExplicitJdbcTransaction(prefix + id, explicit, c, this);
protected SpiTransaction createTransaction(boolean explicit, Connection c) {
return new ExplicitJdbcTransaction(nextTxnId(), explicit, c, this);
}
/**
@@ -31,8 +31,12 @@ class SavepointTransaction extends SpiTransactionProxy {
this.transaction = transaction;
this.connection = transaction.getInternalConnection();
this.savepoint = connection.setSavepoint();
int savepointId = savepoint.getSavepointId();
this.spPrefix = "sp[" + savepointId + "] ";
if (manager.isTxnDebug()) {
int savepointId = manager.isSupportsSavepointId() ? savepoint.getSavepointId() : 0;
this.spPrefix = "sp[" + savepointId + "] ";
} else {
this.spPrefix = "sp[] ";
}
this.logPrefix = transaction.getLogPrefix() + spPrefix;
}
@@ -6,15 +6,12 @@ import io.ebeaninternal.api.SpiTransaction;
import javax.persistence.PersistenceException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.atomic.AtomicLong;
/**
* Creates transactions with implementations for basic mode and multi-tenancy mode.
*/
abstract class TransactionFactory {
final AtomicLong counter = new AtomicLong(1000);
final TransactionManager manager;
TransactionFactory(TransactionManager manager) {
@@ -52,7 +52,7 @@ class TransactionFactoryBasic extends TransactionFactory {
}
private SpiTransaction create(boolean explicit, Connection c) {
return manager.createTransaction(explicit, c, counter.incrementAndGet());
return manager.createTransaction(explicit, c);
}
}
@@ -43,7 +43,7 @@ class TransactionFactoryTenant extends TransactionFactory {
tenantId = tenantProvider.currentId();
}
connection = dataSourceSupplier.getConnection(tenantId);
SpiTransaction transaction = manager.createTransaction(explicit, connection, counter.incrementAndGet());
SpiTransaction transaction = manager.createTransaction(explicit, connection);
transaction.setTenantId(tenantId);
return transaction;
@@ -45,6 +45,7 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
/**
* Manages transactions.
@@ -73,6 +74,8 @@ public class TransactionManager implements SpiTransactionManager {
private final String externalTransPrefix;
private final AtomicLong counter = new AtomicLong(1000L);
/**
* The dataSource of connections.
*/
@@ -129,6 +132,7 @@ public class TransactionManager implements SpiTransactionManager {
private final SpiLogManager logManager;
private final SpiLogger txnLogger;
private final boolean txnDebug;
private final DatabasePlatform databasePlatform;
@@ -141,6 +145,7 @@ public class TransactionManager implements SpiTransactionManager {
private final TableModState tableModState;
private final ServerCacheNotify cacheNotify;
private final boolean supportsSavepointId;
/**
* Create the TransactionManager
@@ -149,7 +154,9 @@ public class TransactionManager implements SpiTransactionManager {
this.logManager = options.logManager;
this.txnLogger = logManager.txn();
this.txnDebug = txnLogger.isDebug();
this.databasePlatform = options.config.getDatabasePlatform();
this.supportsSavepointId = databasePlatform.isSupportsSavepointId();
this.skipCacheAfterWrite = options.config.isSkipCacheAfterWrite();
this.notifyL2CacheInForeground = options.notifyL2CacheInForeground;
this.persistBatch = PersistBatch.ALL == options.config.getPersistBatch();
@@ -242,6 +249,13 @@ public class TransactionManager implements SpiTransactionManager {
}
}
/**
* Return true if the DB platform supports SavepointId().
*/
boolean isSupportsSavepointId() {
return supportsSavepointId;
}
boolean isDocStoreActive() {
return docStoreActive;
}
@@ -352,9 +366,15 @@ public class TransactionManager implements SpiTransactionManager {
/**
* Create a new transaction.
*/
SpiTransaction createTransaction(boolean explicit, Connection c, long id) {
SpiTransaction createTransaction(boolean explicit, Connection c) {
return new JdbcTransaction(nextTxnId(), explicit, c, this);
}
return new JdbcTransaction(prefix + id, explicit, c, this);
/**
* Return the next transaction id.
*/
String nextTxnId() {
return txnDebug ? prefix + counter.incrementAndGet() : prefix;
}
/**
@@ -728,6 +748,13 @@ public class TransactionManager implements SpiTransactionManager {
}
}
/**
* Return true if Transaction debug is on.
*/
public boolean isTxnDebug() {
return txnDebug;
}
public SpiLogManager log() {
return logManager;
}