String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
inputStream.close();
//创建 SqlSession
SqlSession session1 = sqlSessionFactory.openSession();
TUserMapper userMapper1 = session1.getMapper(TUserMapper.class);
List<TUser> list1 = userMapper1.selectByEmailAndSex(email, sex);
一级缓存
一级缓存默认会启用,想要关闭一级缓存可以在 select 标签上配置 flushCache="true"
一级缓存存在于 SqlSession 的生命周期中,在一个 SqlSession 中查询时, MyBatis 会把以下信息通过算法生成键值:
- namespace.id
- 指定查询结果集的范围(分页信息)
- 查询所使用的 SQL 语句
- 用户传递给 SQL 语句的实际参数值
将键值和查询结果存入一个 Map 对象中。如果在同一个 SqlSession 中执以上四点完全一致,那么通过算法会生成相同的键值,当 Map 中已经存在该键值时,则会返中缓存中的对象。
任何的 INSERT、 UPDATE、DELETE 操作都会清空一级缓存。
SqlSession :代表一次数据库连接,一般通过调用 Mapper 访问数据库,也可以直接发送 SQL 执行。线程不安全,要保证线程独享(方法级)。
二级缓存
二级缓存存在于 SqlSessionFactory 的生命周期中,可以理解为跨 SqlSession;缓存是以 namespace(在 Mapper.xml 文件中配置)为单位的,不同 namespace下的操作互不影响。
setting 参数 cacheEnabled,这个参数是二级缓存的全局开关,默认值是 true,如果把这个参数设置为 false,即使有后面的二级缓存配置,也不会生效。
开启二级缓存,在 Mapper.xml 文件中配置:
<cache eviction=“LRU" flushInterval="60000" size="512" readOnly="true"/>
这段配置有如下意义:
Mapper.xml 中的所有 select 语句将会被缓存。
Mapper.xml 中的所有 insert,update 和 delete 语句会刷新缓存。
缓存会使用 Least Recently Used(LRU,最近最少使用的) 算法来回收。
缓存刷新间隔 60000 ms。
缓存会存储列表集合或对象(无论查询方法返回什么)的 512个引用。
缓存会被视为是只读的缓存。
使用二级缓存容易岀现脏读,建议避免使用二级缓存,在业务层使用可控制的缓存代替更好。
为什么出现脏读?
因为不同的 Mapper.xml 可以操作同一张表,而不同的 Mapper.xml 对应不同的缓存。如果用一个 Mapper.xml 对一张表进行了增删改,只会刷新自己的二级缓存,不会刷新另一个 Mapper.xml 的二级缓存。
结构图
图中,namespaceB 和 namespaceC 共用了一个二级缓存,因为是可以这样配置的:
<cache-ref namespace=""/>
如果两个 Mapper.xml 里面所包含的表,不会在另外的 Mapper.xml 里出现,那么它们就可以通过上面的配置,共用一个二级缓存。