• MyBatis 事务源码分析


    先来看看在JAVA事务的相关技术,在JAVA中有两类事务,JDBC事务和JTA事务,如果是JDBC类型的事务,则是由Connection类来控制的。如果创建一个Connection对象时,没有显示调用

    setTransactionIsolation(int level) 方法,则Connection使用当前数据库默认的事务隔离级别,数据库的默认事务隔离级别可以通过相应的SQL语句进行查询,例如在Mysql数据库下可使用 select @@tx_isolation;语句查看当前数据库的事务隔离级别。

    JDBC的Connection类针对事务的隔离性定义了五个隔离级别。

    Connection.TRANSACTION_NONE

    Connection.TRANSACTION_READ_COMMITTED

    Connection.TRANSACTION_READ_UNCOMMITTED

    Connection.TRANSACTION_REPEATABLE_READ

    Connection.TRANSACTION_SERIALIZABLE

    在mybatis中,有一个事务管理器的配置,其中type属性可以配置事务的类型,提供了JDBC或MANAGED的配置属性,这就说明在mybatis中事务的管理方式有两个事务管理器的实现,都是针对JDBC事务的事务管理器(非JTA事务),分别是:

      org.apache.ibatis.transaction.jdbc.JdbcTransaction

      org.apache.ibatis.transaction.managed.ManagedTransaction

    这两个类都实现了org.apache.ibatis.transaction.Transaction接口,Transaction接口定义了如下方法:

       Connection getConnection() throws SQLException;
       void commit() throws SQLException;
       void rollback() throws SQLException;
       void close() throws SQLException;

    通过这些方法可以看出这个接口实际是对Connection类进行了包装,包括了Connection的创建、提交、回滚、关闭动作。并且,其中ManagedTransaction类的commit方法和rollback方法中没有做任何事,也就是说这个类是不控制事务的提交和回滚的,而交由外部容器去管理事务的提交与回滚,外部容器(可以是Spring 容器或EJB容器)通过声明式事务的方式进行管事。

    在mybatis中,通过一个Enum类org.apache.ibatis.session.TransactionIsolationLevel

    来定义了事务的隔离级别:

    public enum TransactionIsolationLevel {
      NONE(Connection.TRANSACTION_NONE),
      READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED),
      READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED),
      REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ),
      SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE);
    
      private final int level;
    
      private TransactionIsolationLevel(int level) {
        this.level = level;
      }
    
      public int getLevel() {
        return level;
      }
    }

    TransactionIsolationLevel类中定义的事务隔离级别其实就是引用了Connection类中的事务隔离级别,下面分别对这几种隔离级别进行说明: 

    TRANSACTION_NONE:表示不支持事务的常量

    TRANSACTION_READ_UNCOMMITTED:表示可以发生脏读 (dirty read)、不可重复读和虚读 (phantom read) 的常量

    TRANSACTION_READ_COMMITTED:不可重复读和虚读可以发生

    TRANSACTION_REPEATABLE_READ:虚读可以发生

    TRANSACTION_SERIALIZABLE:指示不可以发生脏读、不可重复读和虚读的常量。

    再来理解下什么是脏读、不能重复读、虚读(又叫幻读)

    脏读:如果一个事务对数据进行了更新,但事务还没有提交,另一个事务就可以“看到”该事务没有提交的更新结果。这样造成的问题是,如果第一个事务回滚,那么第二个事务在此之前所“看到”的数据就是一笔脏数据。

    不可重复读:指同个事务在整个事务过程中对同一笔数据进行读取,每次读取结果都不同。如果事务1在事务2的更新操作之前读取一次数据,在事务2的更新操作之后再读取同一笔数据一次,两次结果是不同的。所以TRANSACTION_READ_COMMITTED是无法避免不可重复读和虚读。

    幻读:指同样一个查询在整个事务过程中多次执行后,查询所得的结果集是不一样的。幻读针对的是多笔记录。

    最后再总结下:mybatis只是对JDBC事务提供了事务管理器的封装,如果想在mybatis中使用JTA事务,需要我们自行实现org.apache.ibatis.transaction.Transaction接口,对此Spring框架提供了解决方案,可能通过mybatis+spring+atomikos的整合来完成。或者采用EJB容器也可以提供JTA事务的支持。

  • 相关阅读:
    HCL Domino/Notes专业课程和认证体系介绍
    VSLAM视觉里程计总结
    为什么科技型企业需要“贯标”?
    今天给大家介绍一篇基于javaWeb的汽车订票系统的设计与实现
    信息化发展49
    【回眸】Linux知识串讲复习(上)
    Mybatis-Plus的一些优雅用法
    2023计算机毕业设计SSM最新选题之java企业员工信息管理系统677du
    python实现遗传算法,并绘制训练过程以及参数对比
    稀土掺杂氟化物纳米荧光微球/稀土荧光磁性纳米微球Fe3O4@PHEMA-RE的制备方法
  • 原文地址:https://blog.csdn.net/omygodvv/article/details/134520485