1.架构图
1.接口层
Mybatis和数据库的交互有两种方式
- 使用传统的MyBatis提供的API
- 使用Mapper接口
1.1使用传统的MyBatis提供的API
这是传统的传递Statement Id和查询参数给SqlSession对象,使用SqlSession对象完成和数据库的交互;MyBatis提供了非常方便和简单的API,让用户实现对数据库的操作,和对数据库连接信息和自身信息的维护工作
2.Mapper接口
MyBatis 将配置文件中的每一个节点抽象为一个 Mapper 接口
上图就是我们开发中经常会用到的方式,将xml和mapper接口结合起来实现对数据库的操作,实现了面向接口编程和0配置
mybatis编程流程
创建 SqlSessionFactory 对象。
通过 SqlSessionFactory 获取 SqlSession 对象。
通过 SqlSession 获得 Mapper 代理对象。
通过 Mapper 代理对象,执行数据库操作。
执行成功,则使用 SqlSession 提交事务。
执行失败,则使用 SqlSession 回滚事务。
最终,关闭会话。
2.缓存机制
2.1 一级缓存
在没有配置的默认情况下,默认开启一级缓存
一级缓存只是相对于同一个SqlSession而言,mybatis提供了一级缓存,用来储存使用同一个SqlSession对象调用一个Mapper方法,这样的操作只执行一次,因为在SelSession第一次查询后,Mybatis就会将其存放于缓存中,下次查询直接去缓存中取结果
如何配置一级缓存呢?
<setting name="localCacheScope" value="SESSION"/>
SESSION或者STATEMENT,默认是SESSION级别,即在一个MyBatis会话中执行的所有语句,都会共享这一个缓存。一种是STATEMENT级别,可以理解为缓存只对当前执行的这一个Statement有效。
分析
- 在会话级别下,完全相同的查询只有在第一次查询的时候会查询数据库,剩下的就是去一级缓存中取
- 如果对数据库进行了增删改,缓存就会失效
- 当建立两个Session时,一个Session的更新不会被另外一个Session获取,就会出现读脏数据的情况
怎么判断某两次查询是完全相同的查询?
mybatis认为,对于两次查询,如果以下条件都完全一样,那么就认为它们是完全相同的两次查询。
- 传入的statementId
- 查询时要求的结果集中的结果范围
- 这次查询所产生的最终要传递给JDBC java.sql.Preparedstatement的Sql语句字符串(boundSql.getSql() )
- 传递给java.sql.Statement要设置的参数值
STATEMENT级别
一级缓存的脏数据
一级缓存是默认是会话级别的,当你开启2个sqlsession时,一个增删改,另外一个查询就会出现脏数据
如何配置
<setting name="localCacheScope" value="SESSION"/>
##### STATEMENT级别
如何配置
<settings>
<setting name="localCacheScope" value="STATEMENT"/>
</settings>
STATEMENT级别的缓存,只针对当前执行的这一statement有效
总结
MyBatis一级缓存的生命周期和SqlSession一致。
MyBatis一级缓存内部设计简单,只是一个没有容量限定的HashMap,在缓存的功能性上有所欠缺。
MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement。
2.2 二级缓存
二级缓存是Application级别的缓存
二级缓存开启后,同一个namespace下的所有操作语句,都影响着同一个Cache,即二级缓存被多个SqlSession共享,是一个全局的变量。
当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。
小结
- MyBatis的二级缓存相对于一级缓存来说,实现了SqlSession之间缓存数据的共享,同时粒度更加的细,能够到namespace级别,通过Cache接口实现类不同的组合,对Cache的可控性也更强。
- MyBatis在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻。
- 在分布式环境下,由于默认的MyBatis Cache实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将MyBatis的Cache接口实现,有一定的开发成本,直接使用Redis、Memcached等分布式缓存可能成本更低,安全性也更高。