我们在使用 mybatis结合spring事物都是按照标准的模板进行处理,这让我们只是知其然而不知其所以然。这让我情何以堪,所以必须阅读源码并加上调试,搞懂其处理机制
在使用mybatis-spring时,mybatis-spring 官网的入门教程中有如下说明:
只需要往spring容器中注入该bean就完成了mybatis与spring事物的关联。具体如何关联的,还是得阅读源码才能知晓。这个我们放到下次再说。
在阅读mybatis-spring的源码时我看到了
TransactionAwareDataSourceProxy.java 这个类,在网上搜了一下,并阅读spring的官方文档,大致是说,该类是普通数据源的代理类,可以让普通数据源感知到spring的事物上下文。刚开始并不是很理解这句话是什么意思。可以这样理解,如果我们想使用spring的事物,但不使用spring的jdbcTemplate,就使用的原生的jdbc代码,那么我们可以使用TransactionAwareDataSourceProxy将原生jdbc与spring事物关联起来。具体代码如下:
/**
* 以上所有都是可以调用DataSourceUtils化简代码,而JdbcTemplate又是调用DataSourceUtils的。所以在 Spring文档中要求尽量首先使用JdbcTemplate,其次是用DataSourceUtils来获取和释放连接。至于 TransactionAwareDataSourceProxy,那是下策的下策。不过可以将Spring事务管理和遗留代码无缝集成。
* 所以如某位朋友说要使用Spring的事务管理,但是又不想用JdbcTemplate,那么可以考虑TransactionAwareDataSourceProxy。这个类是原来DataSource的代理。
* 其次,想使用Spring事物,又不想对Spring进行依赖是不可能的。与其试图自己模拟DataSourceUtils,不如直接使用现成的。
*
* 下面就是验证TransactionAwareDataSourceProxy的作用
*/
@Test
public void test5() {
Connection connection = null;
DataSourceTransactionManager dataSourceTransactionManager = null;
TransactionStatus transaction = null;
TransactionAwareDataSourceProxy transactionAwareDataSourceProxy = null;
try {
//创建数据源
SimpleDriverDataSource simpleDriverDataSource = new SimpleDriverDataSource();
simpleDriverDataSource.setDriverClass(com.mysql.jdbc.Driver.class);
simpleDriverDataSource.setPassword("test1234");
simpleDriverDataSource.setUsername("root");
simpleDriverDataSource.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF8");
//创建数据源代理
transactionAwareDataSourceProxy = new TransactionAwareDataSourceProxy();
transactionAwareDataSourceProxy.setTargetDataSource(simpleDriverDataSource);
transactionAwareDataSourceProxy.afterPropertiesSet();
//开启spring事物管理
dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(transactionAwareDataSourceProxy);
dataSourceTransactionManager.afterPropertiesSet();
DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
//开启事物并创建链接,并设置事物属性,将链接放到ThreadLocal中
transaction = dataSourceTransactionManager.getTransaction(defaultTransactionDefinition);
//通过spring的数据源代理,获取已经创建了的链接,将原生jdbc与spring事物关联起来
connection = transactionAwareDataSourceProxy.getConnection();
connection.setAutoCommit(false);
PreparedStatement preparedStatement = connection.prepareStatement("update user set name = ? where id = ?");
preparedStatement.setString(1, "test");
preparedStatement.setInt(2, 2);
preparedStatement.executeUpdate();
} catch (Exception e) {
try {
dataSourceTransactionManager.rollback(transaction);
} catch (Exception e1) {
}
} finally {
try {
/*
事物提交会自动关闭链接,具体由DataSourceUtils.releaseConnection(this.connection, this.dataSource);这个方法关闭
该方法广泛用于spring的jdbcTemplate(即spring jdbc中),mybatis-spring的SpringManagedTransaction,TransactionAwareDataSourceProxy,
DataSourceTransactionManager
*/
dataSourceTransactionManager.commit(transaction);
} catch (Exception e2) {
}
}
}
如果我们不使用TransactionAwareDataSourceProxy.java 也想将原生jdbc与spring事物结合呢,如何处理。代码如下:
@Test
public void test6() {
Connection connection = null;
DataSourceTransactionManager dataSourceTransactionManager = null;
TransactionStatus transaction = null;
TransactionAwareDataSourceProxy transactionAwareDataSourceProxy = null;
try {
//创建数据源
SimpleDriverDataSource simpleDriverDataSource = new SimpleDriverDataSource();
simpleDriverDataSource.setDriverClass(com.mysql.jdbc.Driver.class);
simpleDriverDataSource.setPassword("test1234");
simpleDriverDataSource.setUsername("root");
simpleDriverDataSource.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF8");
//开启spring事物管理
dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(simpleDriverDataSource);
dataSourceTransactionManager.afterPropertiesSet();
DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
//开启事物并创建链接,并设置事物属性,将链接放到ThreadLocal中
transaction = dataSourceTransactionManager.getTransaction(defaultTransactionDefinition);
//直接通过DataSourceUtils获取已经创建了的链接
connection = DataSourceUtils.getConnection(simpleDriverDataSource);
connection = transactionAwareDataSourceProxy.getConnection();
connection.setAutoCommit(false);
PreparedStatement preparedStatement = connection.prepareStatement("update user set name = ? where id = ?");
preparedStatement.setString(1, "test");
preparedStatement.setInt(2, 2);
preparedStatement.executeUpdate();
} catch (Exception e) {
try {
dataSourceTransactionManager.rollback(transaction);
} catch (Exception e1) {
}
} finally {
try {
/*
事物提交会自动关闭链接,具体由DataSourceUtils.releaseConnection(this.connection, this.dataSource);这个方法关闭
该方法广泛用于spring的jdbcTemplate(即spring jdbc中),mybatis-spring的SpringManagedTransaction,TransactionAwareDataSourceProxy,
DataSourceTransactionManager
*/
dataSourceTransactionManager.commit(transaction);
} catch (Exception e2) {
}
}
}
mybatis-spring就是使用的方式二将mybatis与spring事物进行关联的