前文我们讨论了抽象的TransactionManager
实现AbstractPlatformTransactionManager
,其定义诸多模板方法,主要目的是处理事务的传播行为,在合适的时机挂起当前事务,本事务完成后重放挂起的事务,参见AbstractPlatformTransactionManager解析,而DataSourceTransactionManager
作为抽象类的具体实现,就是实现了对与DB数据源如何创建事务,提交事务等等,也就是对抽象类中抽象方法的实现。
- doGetTransaction()
- isExistingTransaction()判断当前是否存在事务
- doBegin()开启事务模板方法
- doSuspend()挂起事务扩展逻辑
- doResume()恢复事务扩展逻辑
- doCommit()具体如何提交
- doRollback()具体如何回滚
顾明思意,这个具体实现类主要针对关系型数据库而实现,其字段属性中就包含dataSource字段。
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, InitializingBean {
@Nullable
private DataSource dataSource; // 数据源连接池,可获取具体的物理连接,如mysql连接
private boolean enforceReadOnly = false;
public DataSourceTransactionManager() {
setNestedTransactionAllowed(true);
}
public DataSourceTransactionManager(DataSource dataSource) {
this();
setDataSource(dataSource);
afterPropertiesSet();
}
}
对抽象方法的实现
// 获取具体的事务对象
@Override
protected Object doGetTransaction() {
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
@Override
protected boolean isExistingTransaction(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
}
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
// 新建事务对象
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
//从连接池中获取连接,并封装到当前事务对象中
Connection newCon = obtainDataSource().getConnection();
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
// 隔离级别
txObject.setPreviousIsolationLevel(previousIsolationLevel);
// 是否只读
txObject.setReadOnly(definition.isReadOnly());
// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
// so we don't want to do it unnecessarily (for example if we've explicitly
// configured the connection pool to set it already).
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
// 设置手动提交
con.setAutoCommit(false);
}
// 将事务定义信息配置到具体的物理连接上(只读等)
prepareTransactionalConnection(con, definition);
txObject.getConnectionHolder().setTransactionActive(true);
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
// Bind the connection holder to the thread.
if (txObject.isNewConnectionHolder()) {
// 绑定连接到当前线程ThreadLocalMap
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
} catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, obtainDataSource());
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
// 具体的挂起当前事务逻辑
@Override
protected Object doSuspend(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
txObject.setConnectionHolder(null);
// 将连接从ThreadLocalMap中移除并返回
return TransactionSynchronizationManager.unbindResource(obtainDataSource());
}
// 将连接绑定到线程的ThreadLocalMap中
@Override
protected void doResume(@Nullable Object transaction, Object suspendedResources) {
// 恢复挂起的连接(事务)
TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources);
}
@Override
protected void doCommit(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
try {
// 调用物理连接的提交
con.commit();
}
catch (SQLException ex) {
throw translateException("JDBC commit", ex);
}
}
// 具体的回滚方法,调用物理连接的回滚
@Override
protected void doRollback(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
try {
con.rollback();
}
catch (SQLException ex) {
throw translateException("JDBC rollback", ex);
}
}
// 设置事务只读
protected void prepareTransactionalConnection(Connection con, TransactionDefinition definition)
throws SQLException {
if (isEnforceReadOnly() && definition.isReadOnly()) {
try (Statement stmt = con.createStatement()) {
stmt.executeUpdate("SET TRANSACTION READ ONLY");
}
}
}
具体事务对象类
private static class DataSourceTransactionObject extends JdbcTransactionObjectSupport {
private boolean newConnectionHolder;
private boolean mustRestoreAutoCommit;
public void setConnectionHolder(@Nullable ConnectionHolder connectionHolder, boolean newConnectionHolder) {
super.setConnectionHolder(connectionHolder);
this.newConnectionHolder = newConnectionHolder;
}
public void setRollbackOnly() {
getConnectionHolder().setRollbackOnly();
}
@Override
public boolean isRollbackOnly() {
return getConnectionHolder().isRollbackOnly();
}
@Override
public void flush() {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationUtils.triggerFlush();
}
}
}
//
public abstract class JdbcTransactionObjectSupport implements SavepointManager, SmartTransactionObject {
@Nullable
private ConnectionHolder connectionHolder;
@Nullable
private Integer previousIsolationLevel;
private boolean readOnly = false;
private boolean savepointAllowed = false;
}