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
的事务是交给容器来操作管理的.