网站版面布局设计的原则,搜狗推广手机客户端,信用建设网站动态信息报送制度,erp管理系统介绍视频教程_免费高速下载|百度网盘-分享无限制 (baidu.com)
MyBatis 有一套灵活而强大的缓存机制#xff0c;主要分为两级缓存#xff1a;一级缓存#xff08;本地缓存#xff09;和二级缓存#xff08;全局缓存#xff09;。 一级缓存#xff08;本地缓存#xff09;主要分为两级缓存一级缓存本地缓存和二级缓存全局缓存。 一级缓存本地缓存 一级缓存是 MyBatis 默认开启的缓存它指的是在同一个 SqlSession 中执行相同 SQL 语句时第一次查询的结果会被缓存起来后续再执行相同的查询直接从缓存中获取结果而不再去查询数据库。 一级缓存是基于 SqlSession 的生命周期的当 SqlSession 关闭时一级缓存也就失效了。 一级缓存可以通过清空缓存或提交事务来手动刷新默认情况下只要 SqlSession执行一条语句就会刷新不会等到 SqlSession结束不像二级缓存 一级缓存在进行DML操作后会使得缓存失效 一个会话DML操作只会重置当前会话的缓存不会重置其他会话的缓存也就是说其他会话缓存是不会更新的 二级缓存全局缓存 二级缓存是全局缓存可以跨多个 SqlSession 共享缓存但是只有当一个SqlSession结束之后会刷新二级缓存。所以当 SqlSession1和 SqlSession2都没结束且查询同样内容的时候不会调用二级缓存因为二级缓存啥都没有。 二级缓存需要在 MyBatis 的配置文件中进行配置启用并且需要在映射文件中指定哪些语句使用二级缓存。 不希望某个方法开启缓存呢我们可以添加useCache属性来关闭缓存 select idgetStudentBySid resultTypeStudent useCachefalseselect * from student where sid #{sid}
/select 对于同一个 namespace 下的语句如果开启了二级缓存它们的查询结果会被缓存在一个全局的缓存区域中当其他 SqlSession 执行相同的查询时可以从全局缓存中获取结果。 二级缓存是基于 namespace 级别的不同的 namespace 有独立的缓存区域它们之间不会相互影响。 二级缓存默认是开启的但需要在映射文件中明确指定 cache/ 元素才会对该 namespace 启用缓存。 mapper namespacecom.example.BlogMappercacheevictionFIFOflushInterval60000size512readOnlytrue/!-- 其他映射语句 --
/mappernamespacecom.example.BlogMapper指定缓存的 namespace即当前映射文件所属的命名空间。这个命名空间用于标识二级缓存的作用范围是一个唯一的标识符通常与映射器接口或者类的全路径名相对应。evictionFIFO指定缓存的淘汰策略。在这里FIFO 表示采用先进先出First In, First Out策略即最先进入缓存的数据最先被淘汰。flushInterval60000指定缓存刷新的时间间隔单位为毫秒。在这里设置为 60000 毫秒即 60 秒表示 MyBatis 会定期刷新缓存清理过期的缓存项。size512指定缓存的最大项数。当缓存中的项数达到设定的值时MyBatis 会尝试清理缓存。readOnlytrue指定是否只读。设置为 true 时表示缓存只读不会修改缓存中的数据可以提高性能。默认值为 false。readOnlytrue指定是否只读。设置为 true 时表示缓存只读不会修改缓存中的数据可以提高性能。默认值为 false。 二级缓存的实现是可插拔的可以自定义缓存实现如使用 Ehcache、Redis 等。 添加了二级缓存之后会先从二级缓存中查找数据当二级缓存中没有时才会从一级缓存中获取当一级缓存中都还没有数据时才会请求数据库
需要注意的是缓存机制虽然能提高查询性能但在一些更新操作例如插入、更新、删除时可能会导致缓存的数据不一致。因此在执行这类操作时MyBatis 会自动清空相关的缓存保证数据的正确性。开发者也可以通过手动清理缓存来控制缓存的行为。 虽然缓存机制给我们提供了很大的性能提升但是缓存存在一个问题我们之前在计算机组成原理中可能学习过缓存一致性问题也就是说当多个CPU在操作自己的缓存时可能会出现各自的缓存内容不同步的问题而Mybatis也会这样我们来看看这个例子
public static void main(String[] args) throws InterruptedException {try (SqlSession sqlSession MybatisUtil.getSession(true)){TestMapper testMapper sqlSession.getMapper(TestMapper.class);while (true){Thread.sleep(3000);System.out.println(testMapper.getStudentBySid(1));}}
}我们现在循环地每三秒读取一次而在这个过程中我们使用IDEA手动修改数据库中的数据将1号同学的学号改成100.
结果是依小明的sid并没有发生改变这也证明了Mybatis的缓存在生效因为我们是从外部进行修改Mybatis不知道我们修改了数据所以依然在使用缓存中的数据但是这样很明显是不正确的因此如果存在多台服务器或者是多个程序都在使用Mybatis操作同一个数据库并且都开启了缓存需要解决这个问题要么就得关闭Mybatis的缓存来保证一致性
settingssetting namecacheEnabled valuefalse/
/settingscacheEnabled 是一个全局开关用于控制是否开启缓存。在这里将其值设置为 false表示禁用缓存。
select idgetStudentBySid resultTypeStudent useCachefalse flushCachetrueselect * from student where sid #{sid}
/selectuseCachefalse这个属性用于指定是否使用缓存。在这里useCache 被设置为 false表示禁用缓存。即使全局缓存配置是启用的这个查询也不会使用缓存。 flushCachetrue这个属性用于指定是否刷新缓存。在这里flushCache 被设置为 true表示在执行这个查询之前会刷新清空缓存。即使全局缓存是启用的这个查询会强制刷新缓存确保获取最新的结果。
要么就需要实现缓存共用也就是让所有的Mybatis都使用同一个缓存进行数据存取在后面我们会继续学习Redis、Ehcache、Memcache等缓存框架通过使用这些工具就能够很好地解决缓存一致性问题