10.4 MyBatis事务管理 10.4.3事务的配置创建和使用
1.事务的配置
我们在使用MyBatis时,一般会在MyBatis的根配置文件mybatis-config.xml中定义类似如下的信息:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | <environment id="mysql"><transactionManager type="JDBC"/>
 <dataSource type="pooled">
 <property
 name="driver"
 value="${driver}"/>
 <property
 name="url"
 value="${url}"/>
 <property
 name="username"
 value="${username}"/>
 <property
 name="password"
 value="${password}"/>
 </dataSource>
 </environment>
 
 | 
environment标签定义了连接某个数据库的信息,其子标签transactionManager的type属性决定我们用什么类型的事务管理机制。
如何查看mybatis源码
mybatis的源码放在github上了,所以到github上即可查看mybatis的源码.地址为:
https://github.com/mybatis/mybatis-3/tree/master/src/main/java/org/apache/ibatis
2.事务工厂的创建
MyBatis事务的创建是交给org.apache.ibatis.transaction.TransactionFactory事务工厂来完成的。如果我们将transactionManager标签的type属性配置为JDBC,那么,在MyBatis初始化解析environment标签时,会根据type="JDBC“创建一个JdbcTransactionFactory工厂.
- 如果type="JDBC",则MyBatis会创建一个JdbcTransactionFactory的实例;
- 如果type="MANAGED",则MyBatis会创建一个MangedTransactionFactory的实例。
3.事务工厂TransactionFactory
通过事务工厂TransactionFactory很容易获取到Transaction对象实例。我们以JdbcTransaction为例,看一下JdbcTransactionFactory是怎样生成JdbcTransaction的。
JdbcTransaction源代码如下:
如下
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | public class JdbcTransactionFactory implements TransactionFactory {@Override
 public void setProperties(Properties props) {
 }
 
 @Override
 public Transaction newTransaction(Connection conn) {
 return new JdbcTransaction(conn);
 }
 
 @Override
 public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
 return new JdbcTransaction(ds, level, autoCommit);
 }
 }
 
 | 
如上代码所示,JdbcTransactionFactory会创建JDBC类型的Transaction,即JdbcTransaction。类似地,ManagedTransactionFactory也会创建ManagedTransaction。下面我们分别深入解析JdbcTransaction和ManagedTransaction,看它们到底是怎样实现事务管理的.
4.JdbcTransaction
JdbcTransaction可直接使用JDBC的提交和回滚事务管理机制。它依赖于从dataSource中取得的连接connection来管理transaction的作用域,connection对象的获取被延迟到调用getConnection()方法时。如果将autocomt设置为on,开启状态的话,则它会忽略commit和rollback.
也就是说,JdbcTransaction是使用java.sql.Connection上的commit和rollback功能来完成事务操作的,JdbcTransaction只是相当于对java.sql.Connection事务处理进行了再次封装,Transaction的事务管理都是通过java.sql.Connection实现的JdbcTransaction的源代码实现如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 
 | public class JdbcTransaction implements Transaction {private static final Log log = LogFactory.getLog(JdbcTransaction.class);
 
 protected Connection connection;
 
 protected DataSource dataSource;
 
 protected TransactionIsolationLevel level;
 
 protected boolean autoCommit;
 public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
 dataSource = ds;
 level = desiredLevel;
 autoCommit = desiredAutoCommit;
 }
 public JdbcTransaction(Connection connection) {
 this.connection = connection;
 }
 @Override
 public Connection getConnection() throws SQLException {
 if (connection == null) {
 openConnection();
 }
 return connection;
 }
 
 @Override
 public void commit() throws SQLException {
 if (connection != null && !connection.getAutoCommit()) {
 if (log.isDebugEnabled()) {
 log.debug("Committing JDBC Connection [" + connection + "]");
 }
 connection.commit();
 }
 }
 
 @Override
 public void rollback() throws SQLException {
 if (connection != null && !connection.getAutoCommit()) {
 if (log.isDebugEnabled()) {
 log.debug("Rolling back JDBC Connection [" + connection + "]");
 }
 connection.rollback();
 }
 }
 
 @Override
 public void close() throws SQLException {
 if (connection != null) {
 resetAutoCommit();
 if (log.isDebugEnabled()) {
 log.debug("Closing JDBC Connection [" + connection + "]");
 }
 connection.close();
 }
 }
 
 }
 
 | 
从JdbcTransaction类的源代码可以看出,JdbcTransaction就是使用java.sql.Connection上的commit、rollback功能来完成事务操作的.
5.ManagedTransaction
ManagedTransaction让容器来管理事务Transaction的整个生命周期,意思就是说,使用ManagedTransaction的commit和rollback功能不会对事务有任何的影响,它什么都不会做,它将事务管理的权力移交给了容器。ManagedTransaction的源代码如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 
 | public class ManagedTransaction implements Transaction {private static final Log log = LogFactory.getLog(ManagedTransaction.class);
 private DataSource dataSource;
 private TransactionIsolationLevel level;
 private Connection connection;
 private final boolean closeConnection;
 public ManagedTransaction(Connection connection, boolean closeConnection) {
 this.connection = connection;
 this.closeConnection = closeConnection;
 }
 public ManagedTransaction(DataSource ds, TransactionIsolationLevel level, boolean closeConnection) {
 this.dataSource = ds;
 this.level = level;
 this.closeConnection = closeConnection;
 }
 @Override
 public Connection getConnection() throws SQLException {
 if (this.connection == null) {
 openConnection();
 }
 return this.connection;
 }
 @Override
 public void commit() throws SQLException {
 
 }
 @Override
 public void rollback() throws SQLException {
 
 }
 @Override
 public void close() throws SQLException {
 if (this.closeConnection && this.connection != null) {
 if (log.isDebugEnabled()) {
 log.debug("Closing JDBC Connection [" + this.connection + "]");
 }
 this.connection.close();
 }
 }
 protected void openConnection() throws SQLException {
 if (log.isDebugEnabled()) {
 log.debug("Opening JDBC Connection");
 }
 this.connection = this.dataSource.getConnection();
 if (this.level != null) {
 this.connection.setTransactionIsolation(this.level.getLevel());
 }
 }
 @Override
 public Integer getTimeout() throws SQLException {
 return null;
 }
 }
 
 | 
从ManagedTransaction类的源代码可以看出,提交和回滚时它什么都没有做,也就是说,当使用ManagedTransaction时MyBatis的事务是交给容器来操作管理的.