mybatis没有事务管理的能力_Mybatis|事务管理

46c41f2c16a0

1. 什么是事务

事务是指的是一个业务上的最小不可再分单元,通常一个事务对应了一个完整的业务,而一个完整的业务需要批量的DML语句共同联合完成。一般,同一个事务中的SQL语句是保存到数据库中的同一个Transaction对象中,原因是Transaction具有一致性的特征,也就是说事务中如果有任何一条sql语句运行失败,那么这个事务中所有的SQL语句都会被判定为无效SQL。

2. MyBatis事务管理策略

2.1 亲自实现JDBC管理方式

如果Mybatis是单独运行的,没有其他框架管理,此时mybatis内部会对下段代码实现。

con.setAutoCommit(false);

//此处命令通知数据库,从此刻开始从当前Connection通道推送而来的

//SQL语句属于同一个业务中这些SQL语句在数据库中应该保存到同一个

//Transaction中.这个Transaction的行为(commit,rollback)由当前Connection

管理.

try{

//推送sql语句命令……..;

con.commit();//通知Transaction提交.

}catch(SQLException ex){

con.rollback();//通知Transaction回滚.

}

2.2 委托实现JDBC管理方式

如果实现Spring+MyBatis,可以将对Transasaction 管理交给Spring框架来管理实现。

开发人员可以在mybatis-configuration.xml 文件中配置,采用指定的管理方式。

46c41f2c16a0

当时,就会调用JdbcTransaction。

当时,调用ManagedTransaction。

3. MyBatis中Transaction接口

mybatis 支持的两种事务类型管理器,Transactions接口中对两种事务管理方式,进行行为约束。有四种方法对事物管理,具体介绍看下面代码。

public interface Transaction {

//JDBC中事务手动管理,需要依靠connection对象,getConnection方法约束取得Connection对象方式。

//一般来说,要么是手动new一个Connection,要么就是从数据库连池获得。

Connection getConnection() throws SQLException;

//设置在什么情况下执行commit()命令

void commit() throws SQLException;

//设置在什么情况下执行rollback()命令

void rollback() throws SQLException;

//业务完毕后,处理Connection对象。

//一般有两种形式,将这个Connection对象销毁,将Connection返回数据库连接池中。

void close() throws SQLException;

//Connection向数据库索要一个Transaction对象时的最大等待时间。

Integer getTimeout() throws SQLException;

}

4. Transaction的接口实现类

Transaction接口中有两个实现类。

4.1 JdbcTransaction

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

public class JdbcTransaction implements Transaction {

private static final Log log = LogFactory.getLog(JdbcTransaction.class);

protected Connection connection;

protected DataSource dataSource;

protected TransactionIsolationLevel level;

// MEMO: We are aware of the typo. See #941

protected boolean autoCommmit;

//数据源、隔离级别、是否自动提交

public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {

dataSource = ds;

level = desiredLevel;

autoCommmit = desiredAutoCommit;

}

//根据当前的数据库连接connection创建transaction

public JdbcTransaction(Connection connection) {

this.connection = connection;

}

//返回一个Connection对象,其中openConnection方法是得到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();

}

}

//close方法中我们可以看到connection被回收到数据库连接池前,执行了一个resetAutoCommit()。

@Override

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

if (log.isDebugEnabled()) {

log.debug("Error resetting autocommit to true "

+ "before closing the connection. Cause: " + e);

}

}

}

/**

* openConnection方法中做了三件事情:

* 1. 数据库连接池得到了一个Connection

* 2. 设置数据库的事务隔离级别

* 3. 调用了con.setAutoCommit(false),再setDesireAutoCommit(autoCommit)。

**/

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

}

@Override

public Integer getTimeout() throws SQLException {

return null;

}

}

4.2 ManagedTransaction

我们可以在这个类中看到它的commit方法和rollback方法没有具体实现。

ManagedTransaction是让容器来管理事务Transaction的整个生命周期,使用ManagedTransaction的commit和rowblkrollback功能不会对事务有任何影响,它没有具体实现,它将事务管理权交给容器来实现。

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 {

// Does nothing

}

@Override

public void rollback() throws SQLException {

// Does nothing

}

@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;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值