Spring的事务处理中,通用的事务处理流程框架是由抽象事务管理器AbstractPlatformTransactionManager来提供的,而具体的底层事务处理实现,由PlatformTransactionManager的具体实现类来实现,如 DataSourceTransactionManager 、JtaTransactionManager和 HibernateTransactionManager等。
对于具体的事务管理器而言,它们只需要处理和具体数据源相关的组件设置就可以了。如doGetTransaction(),doCommit(status)方法等。
本文主要介绍DataSourceTransactionManager中的具体实现。
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, InitializingBean {
//注入数据源
private DataSource dataSource;
//数据源事务处理器默认构造方法,创建一个数据源事务处理器实例,并设置允许嵌套事务
public DataSourceTransactionManager() {
setNestedTransactionAllowed(true);
}
//根据给定数据源,创建一个数据源事务处理器实例
public DataSourceTransactionManager(DataSource dataSource) {
this();
setDataSource(dataSource);
afterPropertiesSet();
}
//设置数据源
public void setDataSource(DataSource dataSource) {
if (dataSource instanceof TransactionAwareDataSourceProxy) {
//如果数据源是一个事务包装数据源代理,则获取事务包装代理的目标数据源
this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();
}
else {
this.dataSource = dataSource;
}
}
//获取数据源
public DataSource getDataSource() {
return this.dataSource;
}
//数据源事务处理器对象构造方法的回调函数
public void afterPropertiesSet() {
if (getDataSource() == null) {
throw new IllegalArgumentException("Property 'dataSource' is required");
}
}
public Object getResourceFactory() {
return getDataSource();
}
//创建事务,对数据库而言,是由Connection来完成事务工作的。该方法把数据库的//Connection对象放到一个ConnectionHolder对象中,然后封装到一个
//DataSourceTransactionObject对象中
protected Object doGetTransaction() {
//创建数据源事务对象
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
//设置数据源事务对象对嵌套事务使用保存点
txObject.setSavepointAllowed(isNestedTransactionAllowed());
//从事务管理容器中获取存放数据库Connection的对象
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
//判断是否已经存在事务
protected boolean isExistingTransaction(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
//根据存放数据库连接的ConnectionHolder的isTransactionActive属性来判断
return (txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive());
}
//处理事务开始的方法
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
//如果数据源事务对象的ConnectionHolder为null或者是事务同步的
if (txObject.getConnectionHolder() == null ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
//获取当前数据源的数据库连接
Connection newCon = this.dataSource.getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
//为数据源事务对象设置ConnectionHolder
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
//设置数据源事务对象的事务同步 txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
//获取数据源事务对象的数据库连接
con = txObject.getConnectionHolder().getConnection();
//根据数据连接和事务属性,获取数据库连接的事务隔离级别
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
//为数据源事务对象设置事务隔离级别
txObject.setPreviousIsolationLevel(previousIsolationLevel);
//如果数据库连接设置了自动事务提交属性,则关闭自动提交
if (con.getAutoCommit()) {
//保存数据库连接设置的自动连接到数据源事务对象中
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
//设置数据库连接自动事务提交属性为false,即禁止自动事务提交
con.setAutoCommit(false);
}
//激活当前数据源事务对象的事务配置
txObject.getConnectionHolder().setTransactionActive(true);
//获取事务配置的超时时长
int timeout = determineTimeout(definition);
//如果事务配置的超时时长不等于事务的默认超时时长
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
//数据源事务对象设置超时时长
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
//把当前数据库Connection和线程绑定
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
}
}
catch (Exception ex) {
DataSourceUtils.releaseConnection(con, this.dataSource);
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
//事务挂起
protected Object doSuspend(Object transaction) {
//获取事务对象
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
//将事务对象中的ConnectionHolders设置为null
txObject.setConnectionHolder(null);
ConnectionHolder conHolder = (ConnectionHolder)
//解除事务对象和当前线程的绑定 TransactionSynchronizationManager.unbindResource(this.dataSource);
return conHolder;
}
//事务恢复
protected void doResume(Object transaction, Object suspendedResources) {
//获取已暂停事务的ConnectionHolder
ConnectionHolder conHolder = (ConnectionHolder) suspendedResources;
//重新将事务对象和当前线程绑定
TransactionSynchronizationManager.bindResource(this.dataSource, conHolder);
}
//事务提交
protected void doCommit(DefaultTransactionStatus status) {
//获取事务对象
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
//通过事务对象获取数据库连接
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Committing JDBC transaction on Connection [" + con + "]");
}
try {
//使用数据库连接手动进行事务提交
con.commit();
}
catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
}
}
//事务回滚
protected void doRollback(DefaultTransactionStatus status) {
//获取事务对象
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
//通过事务对象获取数据库连接
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
}
try {
//通过调用数据库连接的回滚方法完成事务回滚操作
con.rollback();
}
catch (SQLException ex) {
throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
}
}
//设置回滚
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
if (status.isDebug()) {
logger.debug("Setting JDBC transaction [" + txObject.getConnectionHolder().getConnection() +
"] rollback-only");
}
txObject.setRollbackOnly();
}
//操作完成之后清除操作
protected void doCleanupAfterCompletion(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
//移除当前线程绑定的ConnectionHolder
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.unbindResource(this.dataSource);
}
Connection con = txObject.getConnectionHolder().getConnection();
try {
//如果事务对象保存了自动事务提交属性,则设置数据库连接的自动事务提交属性
if (txObject.isMustRestoreAutoCommit()) {
con.setAutoCommit(true);
}
//事务结束后重置数据库连接
DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());
}
catch (Throwable ex) {
logger.debug("Could not reset JDBC Connection after transaction", ex);
}
//如果事务对象中有新的ConnectionHolder
if (txObject.isNewConnectionHolder()) {
if (logger.isDebugEnabled()) {
logger.debug("Releasing JDBC Connection [" + con + "] after transaction");
}
//释放数据库连接
DataSourceUtils.releaseConnection(con, this.dataSource);
}
//清除事务对象的ConnectionHolder
txObject.getConnectionHolder().clear();
}
//数据源事务对象,内部类
private static class DataSourceTransactionObject extends JdbcTransactionObjectSupport {
//是否有新的ConnectionHolder
private boolean newConnectionHolder;
//是否保存自动提交
private boolean mustRestoreAutoCommit;
//设置ConnectionHolder
public void setConnectionHolder(ConnectionHolder connectionHolder, boolean newConnectionHolder) {
//为父类JdbcTransactionObjectSupport设置ConnectionHolder
super.setConnectionHolder(connectionHolder);
this.newConnectionHolder = newConnectionHolder;
}
public boolean isNewConnectionHolder() {
return this.newConnectionHolder;
}
//调用父类JdbcTransactionObjectSupport的相关方法,查询收费存在事务
public boolean hasTransaction() {
return (getConnectionHolder() != null && getConnectionHolder().isTransactionActive());
}
//设置是否保存自动提交
public void setMustRestoreAutoCommit(boolean mustRestoreAutoCommit) {
this.mustRestoreAutoCommit = mustRestoreAutoCommit;
}
public boolean isMustRestoreAutoCommit() {
return this.mustRestoreAutoCommit;
}
//设置数据库连接在操作失败是,是否只回滚处理
public void setRollbackOnly() {
getConnectionHolder().setRollbackOnly();
}
public boolean isRollbackOnly() {
return getConnectionHolder().isRollbackOnly();
}
}
}