基础
定义:
MyBatis 与 Hibernate 相似,都是持久层框架 ,而 MyBatis 是一款 半自动 ORM 工具(object relation mapping) ,其优点有:
- 解除 SQL与程序代码的耦合
- 支持编写动态 SQL 语句
其缺点有:
- SQL 语句的编写工作量较大
- SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库
工作流程:
-
读取全局配置文件,例如数据库连接信息等;加载 SQL 映射文件。
-
构造 SqlSessionFactory
-
创建 SqlSession:由 SqlSessionFactory 创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。
-
Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数(simple / reuse / batch三类)动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。
-
MappedStatement :在 Executor 的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储映射的 SQL 语句的 id、参数信息等。
映射文件中每条 SQL 都对应一个 MappedStatement,使用类的全限定名 + 方法名做 MappedStatement 的唯一标识(由此可知接口中不能有方法重载) -
输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。
-
输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。
接口与映射文件间的工作原理:
Mybatis 运行时使用 JDK 动态代理为 Dao 接口生成代理对象,拦截接口方法,找到 SQL 标签对应的 MappedStatement 执行,然后将执行结果返回。
动态SQL
在 Xml 映射文件中,以标签的形式动态拼接 SQL ,Mybatis 提供了9种动态 SQL 标签:
trim | where | set | foreach | if | choose | when | otherwise | bind
MyBatis 本地的一、二级缓存
一级缓存
一级缓存的使用流程:
一级缓存的使用
如何使用MyBatis一级缓存?开发者只需在MyBatis的配置文件中,添加如下语句,就可以使用一级缓存。共有两个选项,SESSION或者STATEMENT,默认是SESSION级别,即在一个 SqlSession 中执行的所有语句,都会共享这一个缓存。一种是STATEMENT级别,可以理解为缓存只对当前执行的这一个 Statement 有效。
<setting name="localCacheScope" value="SESSION"/>
关于源码与用例可参考本文,对于一级缓存我们需要知道的结论:
-
MyBatis 一级缓存的生命周期和 SqlSession 一致,SqlSession 内的数据修改操作,会刷新缓存。
-
MyBatis 一级缓存内部设计简单,只是一个没有容量限定的 HashMap,在缓存的功能性上有所欠缺。
-
MyBatis 的一级缓存最大范围是 SqlSession 内部,有多个 SqlSession(即分布式环境下)时,数据库写操作会引起脏数据。
与 Spring 整合后的一级缓存
关于源码与用例可参考本文,总结后可得到如下结论:
-
在未开启事务的情况下,每个数据库操作,Spring 都会构建一个新的 SqlSession 出来,所以也无法使用到对应的本地一级缓存。
-
在同一个事务中,每个数据库操作,Spring 都返回同一个 SqlSession,所以可以使用到一级缓存。
二级缓存
默认关闭,实现了 SqlSession 之间缓存数据的共享,但仍然属于本地缓存,不适用于分布式环境,且有一定开发成本,使用 Redis 等一些中间件更合适些。