本篇来聊聊mybatis的事务管理机制,基于mybatis 3.4.6、mybatis-spring 1.3.2。
知识点
- 什么是事务
- mybatis支持的事务管理方式
- mybatis事务管理实现机制
- spring是如何集成的
什么是事务
学过sql的肯定都知道这个概念,事务在sql中是非常重要的概念。这里做一个简单的介绍。
事务( Transaction)由一次或者多次基本操作构成,或者说,事务由一条或者多条 SQL 语句构成,事务中的所有操作是一个整体,要么全部执行成功,要么全部执行失败。它有4个基本的特性,分别是原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability),简称 ACID。
1) 原子性
一个事务中的所有 SQL 语句,要么全部执行成功,要么全部执行失败,不会结束在中间的某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
2) 一致性
在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的数据必须完全符合所有的预设规则,其中包含数据的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
3) 隔离性
数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
4) 持久性
事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
mybatis支持的事务管理方式
mybatis目前支持两种方式管理事务
- 原生jdbc
- 容器托管
先介绍一下原生jdbc,原生jdbc就是我们直接在mybatis的配置文件中配置对应的数据库信息,对应的事务相关操作都由mybatis内置的JdbcTransaction
来完成,相当于是不依赖于任何容器的,配置方式官网也提到了
这里的 type 填 JDBC 就可以了,需要注意的是如果要用原生 jdbc 方式的,必须通过配置文件来实现,不支持 spring 的配置方式。
再说一下容器托管方式。顾名思义就是将事务操作托管给具体的容器来实现。容器是什么意思?简单的理解,我们可以认为就是类似于spring这种存在,结合起来就是mybatis将事务的管理实现交给spring来实现,它有一个好处就是可以和容器共用一个数据库连接,不用两边来各自管理,spring对于mybatis的集成就是自己实现了一个专门的容器托管类来做的。
mybatis事务管理实现机制
mybatis 的事务管理实现比较简单,都在这一块了
这里用到了工厂模式来实现,对于原生的jdbc方式,通过JdbcTransaction
来管理
可以看到这里直接用了数据库连接的提交和回滚操作。
你可能认为托管的实现就是ManagedTransaction
,其实并不是。那为什么有这个类,我猜想这里只是提供了样例般的代码,实际估计也是为了兼容mybatis的不同配置。可以看到它并没有做任何事情
对于TransactionFactory
,它是依附于Environment
中的,mybatis 都是通过Environment
来获取对应的TransactionFactory
,然后再创建相应的Transaction
。这也是为什么我们可以配置不同环境来配置不同数据库信息来做到环境隔离。
而对于Transaction
,它是依附于Executor
的,也就是执行器,这个设计也非常容易理解,因为执行器本身就是对数据库做增删改查操作的,事务也放到里面一起管理非常合理。
spring是如何集成的
通过上面的内容,我们知道 mybatis 支持事务管理托管给容器处理,而 spring 就是这种方式非常经典实现。因为我们目前用的大多是 spring 框架,所以我们在项目中用 mybatis 的时候都会引入mybatis-spring
这个 jar 包,这个包就是 spring 集成 mybatis 的关键所在,里面涉及内容也有不少,但这里只分析事务管理这一块。
对于mybatis的集成,这里有个很关键的类SqlSessionFactoryBean
可以看到这是一个FactoryBean
,就是通过它来获取SqlSessionFactory
的,直接看核心逻辑org.mybatis.spring.SqlSessionFactoryBean#buildSqlSessionFactory
可以看到这里创建了spring实现的事务管理类SpringManagedTransactionFactory
,然后创建了一个Environment
设置到Configuration
中,这样后续 mybatis 在获取事务的时候获取到的都是SpringManagedTransactionFactory
。
所有实现都在这个包下面,结构是不是很熟悉,就是基于 mybatis 的工厂模式那一套。
总结
mybatis的事务管理实现还是相对比较简单的,其实我们平时自己去配置具体的事务管理类也很少,因为如果用的spring,基本不用再自己做什么处理了,但是这个设计还是不错的,直接把相关模块交给容器处理,容器接入也简单。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。