Mybatis作为最流行的持久层框架,当然支持事务的统一管理。
不多说,先来张图热热场…
该图大致概括了mybatis的事务体系。
mybatis事务的分类
1)JDBC :直接简单使用了JDBC 的提交和回滚设置。
2)MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,通常情况下,在mybatis与spring集成时这样设置,因为spring提供了同意的事务管理,mybatis在事务上不需要做任何事情。
配置mybatis事务管理器
在mybatis核心配置文件中
<environments default="mysql_environment">
<environment id="mysql_environment">
<!-- 配置mybatis的事务 -->
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="zhangdd" />
<property name="password" value="zd1991.." />
</dataSource>
</environment>
</environments>
其中<transactionManager/>
节点指定了事务管理器的类型,该节点只有一个type属性。
<environments/>
节点时,会根据<transactionManager/>
和<dataSource>
来创建一个Environment对象: public Environment(String id, TransactionFactory transactionFactory, DataSource dataSource) {
,从这个构造器签名中我们可以看到,事务(Transaction)是由事务工厂(TransactionFactory)创建的。创建事务与创建数据源类似,TransactionFactory是事务工程的顶级接口,其下有两个实现类:JdbcTransactionFactory
和ManagedTransactionFactory
,mybatis根据<transactionManager/>
的type属性来选择用哪种工厂类创建事务。
JDBC Transaction是创建如下:
JdbcTransactionFactory:
public class JdbcTransactionFactory implements TransactionFactory{
public void setProperties(Properties props) {}
public Transaction newTransaction(Connection conn) {
return new JdbcTransaction(conn);
}
public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
return new JdbcTransaction(ds, level, autoCommit);
}
}
JdbcTransaction:
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 autoCommmit;
public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
dataSource = ds;
level = desiredLevel;
autoCommmit = desiredAutoCommit;
}
public JdbcTransaction(Connection connection) {
this.connection = connection;
}
public Connection getConnection() throws SQLException {
if (connection == null) {
openConnection();
}
return connection;
}
public void commit() throws SQLException {
if (connection != null && !connection.getAutoCommit()) {
if (log.isDebugEnabled()) {
log.debug("Committing JDBC Connection [" + connection + "]");
}
connection.commit();
}
}
public void rollback() throws SQLException {
if (connection != null && !connection.getAutoCommit()) {
if (log.isDebugEnabled()) {
log.debug("Rolling back JDBC Connection [" + connection + "]");
}
connection.rollback();
}
}
public void close() throws SQLException {
if (connection != null) {
resetAutoCommit();
if (log.isDebugEnabled()) {
log.debug("Closing JDBC Connection [" + connection + "]");
}
connection.close();
}
}
protected void setDesiredAutoCommit(boolean desiredAutoCommit) {
try {
if (connection.getAutoCommit() != desiredAutoCommit) {
if (log.isDebugEnabled()) {
log.debug("Setting autocommit to " + desiredAutoCommit + " on JDBC Connection [" + connection + "]");
}
connection.setAutoCommit(desiredAutoCommit);
}
} catch (SQLException e) {
throw new TransactionException("Error configuring AutoCommit. "
+ "Your driver may not support getAutoCommit() or setAutoCommit(). "
+ "Requested setting: " + desiredAutoCommit + ". Cause: " + e, e);
}
}
protected void resetAutoCommit() {
try {
if (!connection.getAutoCommit()) {
if (log.isDebugEnabled()) {
log.debug("Resetting autocommit to true on JDBC Connection [" + connection + "]");
}
connection.setAutoCommit(true);
}
} catch (SQLException e) {
log.debug("Error resetting autocommit to true "
+ "before closing the connection. Cause: " + e);
}
}
protected void openConnection() throws SQLException {
if (log.isDebugEnabled()) {
log.debug("Openning JDBC Connection");
}
connection = dataSource.getConnection();
if (level != null) {
connection.setTransactionIsolation(level.getLevel());
}
setDesiredAutoCommit(autoCommmit);
}
}
很显然,JdbcTransaction是通过底层的Connection对象来管理事务的。
ManagedTransactionFactory:
public class ManagedTransactionFactory implements TransactionFactory {
private boolean closeConnection = true;
public void setProperties(Properties props) {
if (props != null) {
String closeConnectionProperty = props.getProperty("closeConnection");
if (closeConnectionProperty != null) {
closeConnection = Boolean.valueOf(closeConnectionProperty);
}
}
}
public Transaction newTransaction(Connection conn) {
return new ManagedTransaction(conn, closeConnection);
}
public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
return new ManagedTransaction(ds, level, closeConnection);
}
}
ManagedTransaction:
public class ManagedTransaction implements Transaction {
private static final Log log = LogFactory.getLog(ManagedTransaction.class);
private DataSource dataSource;
private TransactionIsolationLevel level;
private Connection connection;
private 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;
}
public Connection getConnection() throws SQLException {
if (this.connection == null) {
openConnection();
}
return this.connection;
}
public void commit() throws SQLException {
// Does nothing
}
public void rollback() throws SQLException {
// Does nothing
}
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("Openning JDBC Connection");
}
this.connection = this.dataSource.getConnection();
if (this.level != null) {
this.connection.setTransactionIsolation(this.level.getLevel());
}
}
}
从上面的代码中可以提炼出最重要的几行:
public void commit() throws SQLException {
// Does nothing
}
public void rollback() throws SQLException {
// Does nothing
}
是的,就想你看到的那样,commit()
和rollback()
什么都没有做。
当将事务类型配置成Managed
时,mybatis所有的DML操作都将失效,事务会交由spring或web容器统一管理。