• mybatis源码分析(2)——事务概述


    这篇文章主要对mybatis中的事务做一简单的分析,帮助读者理清一些概念。

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

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

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

    Connection.TRANSACTION_NONE

    Connection.TRANSACTION_READ_COMMITTED

    Connection.TRANSACTION_READ_UNCOMMITTED

    Connection.TRANSACTION_REPEATABLE_READ

    Connection.TRANSACTION_SERIALIZABLE

     

    在mybatis中,有一个事务管理器的配置,其中type属性可以配置事务的类型,提供了JDBCMANAGED的配置属性,这就说明在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中,通过一个Enumorg.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事务的支持。关于具体整合方案,可关注我的后续文章。

    注:Atomikos 是一款 Java/JTA 事务处理工具,其官网需翻墙才能访问。

     

  • 相关阅读:
    Palindrome Partitioning
    Minimum Path Sum
    Maximum Depth of Binary Tree
    Minimum Depth of Binary Tree
    Unique Binary Search Trees II
    Unique Binary Search Trees
    Merge Intervals
    Merge Sorted Array
    Unique Paths II
    C++ Primer Plus 笔记第九章
  • 原文地址:https://www.cnblogs.com/hzhuxin/p/3352758.html
Copyright © 2020-2023  润新知