10.4 MyBatis事务管理 10.4.3事务的配置创建和使用
1.事务的配置
我们在使用MyBatis时,一般会在MyBatis的根配置文件mybatis-config.xml中定义类似如下的信息:
1 2 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源代码如下:
如下
1 2 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的源代码实现如下:
1 2 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的源代码如下:
1 2 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的事务是交给容器来操作管理的.