mybatis事务和MySQL事务_MyBatis事务管理机制

Environment表示着一个数据库的连接,生成后的Environment对象会被设置到Configuration实例中,以供后续的使用。

mybatis事务和MySQL事务_MyBatis事务管理机制_第1张图片

上述一直在讲事务工厂TransactionFactory来创建的Transaction,现在让我们看一下MyBatis中的TransactionFactory的定义吧。

3. 事务工厂TransactionFactory

事务工厂Transaction定义了创建Transaction的两个方法:

通过指定的Connection对象创建Transaction

通过数据源DataSource来创建Transaction

与JDBC 和MANAGED两种Transaction相对应,TransactionFactory有两个对应的实现的子类:如下所示:

mybatis事务和MySQL事务_MyBatis事务管理机制_第2张图片

4. 事务Transaction的创建

通过事务工厂TransactionFactory很容易获取到Transaction对象实例。我们以JdbcTransaction为例,看一下JdbcTransactionFactory是怎样生成JdbcTransaction的,代码如下:

public class JdbcTransactionFactory implements TransactionFactory {

public void setProperties(Properties props) {

}

/**

* 根据给定的数据库连接Connection创建Transaction

* @param conn Existing database connection

* @return

*/

public Transaction newTransaction(Connection conn) {

return new JdbcTransaction(conn);

}

/**

* 根据DataSource、隔离级别和是否自动提交创建Transacion

*

* @param ds

* @param level Desired isolation level

* @param autoCommit Desired autocommit

* @return

*/

public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {

return new JdbcTransaction(ds, level, autoCommit);

}

}

如上说是,JdbcTransactionFactory会创建JDBC类型的Transaction,即JdbcTransaction。类似地,ManagedTransactionFactory也会创建ManagedTransaction。下面我们会分别深入JdbcTranaction 和ManagedTransaction,看它们到底是怎样实现事务管理的。

5. JdbcTransaction

JdbcTransaction直接使用JDBC的提交和回滚事务管理机制 。它依赖与从dataSource中取得的连接connection 来管理transaction 的作用域,connection对象的获取被延迟到调用getConnection()方法。如果autocommit设置为on,开启状态的话,它会忽略commit和rollback。

直观地讲,就是JdbcTransaction是使用的java.sql.Connection 上的commit和rollback功能,JdbcTransaction只是相当于对java.sql.Connection事务处理进行了一次包装(wrapper),Transaction的事务管理都是通过java.sql.Connection实现的。JdbcTransaction的代码实现如下:

/**

* @see JdbcTransactionFactory

*/

/**

* @author Clinton Begin

*/

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;

}

/**

* commit()功能 使用connection的commit()

* @throws SQLException

*/

public void commit() throws SQLException {

if (connection != null && !connection.getAutoCommit()) {

if (log.isDebugEnabled()) {

log.debug("Committing JDBC Connection [" + connection + "]");

}

connection.commit();

}

}

/**

* rollback()功能 使用connection的rollback()

* @throws SQLException

*/

public void rollback() throws SQLException {

if (connection != null && !connection.getAutoCommit()) {

if (log.isDebugEnabled()) {

log.debug("Rolling back JDBC Connection [" + connection + "]");

}

connection.rollback();

}

}

/**

* close()功能 使用connection的close()

* @throws SQLException

*/

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) {

// Only a very poorly implemented driver would fail here,

// and there's not much we can do about that.

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()) {

// MyBatis does not call commit/rollback on a connection if just selects were performed.

// Some databases start transactions with select statements

// and they mandate a commit/rollback before closing the connection.

// A workaround is setting the autocommit to true before closing the connection.

// Sybase throws an exception here.

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("Opening JDBC Connection");

}

connection = dataSource.getConnection();

if (level != null) {

connection.setTransactionIsolation(level.getLevel());

}

setDesiredAutoCommit(autoCommmit);

}

}

6. ManagedTransaction

ManagedTransaction让容器来管理事务Transaction的整个生命周期,意思就是说,使用ManagedTransaction的commit和rollback功能不会对事务有任何的影响,它什么都不会做,它将事务管理的权利移交给了容器来实现。看如下Managed的实现代码大家就会一目了然:

/**

*

* 让容器管理事务transaction的整个生命周期

* connection的获取延迟到getConnection()方法的调用

* 忽略所有的commit和rollback操作

* 默认情况下,可以关闭一个连接connection,也可以配置它不可以关闭一个连接

* 让容器来管理transaction的整个生命周期

* @see ManagedTransactionFactory

*/

/**

* @author Clinton Begin

*/

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("Opening JDBC Connection");

}

this.connection = this.dataSource.getConnection();

if (this.level != null) {

this.connection.setTransactionIsolation(this.level.getLevel());

}

}

}

你可能感兴趣的:(mybatis事务和MySQL事务_MyBatis事务管理机制)