mybatis 缓存
数据模型分析思路
- 每张表记录的数据内容: 分模块对每张表的内容进行熟悉,相当于学习系统需求功能的过程
- 每张表的重要字段: 非空字段、外键字段
- 数据库表与表之间的关系: 外键字段
- 表与表之间的业务关系:建立在某个业务基础之上去分析
mybatis 缓存
mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。
mybaits提供一级缓存,和二级缓存
为什么要用缓存?
如果缓存中有数据就不用从数据库中获取,直接从缓存中获取,大大提高系统性能。
一级缓存:是sqlSession级别的缓存,在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据,不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
是mapper级别(命名空间)的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。 即 同一个命名空间 namspace 下,开辟一个缓存区域,放置该mapper对应的查询缓存数据,即使不同的sqlSession来调用,也可以访问缓存。
注意: 每一个namespace的mapper都有一个二缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同 的二级缓存区域中。
一级缓存查询原理
当修改、删除、添加用户执行commit 时,就会清空一级缓存, 另外因为一级缓存是跟随sqlSession的,一旦sqlSession关闭,则缓存也会被清除,
正式开发,是将mybatis和spring进行整合开发,事务控制在service中。
一个service方法中包括 很多mapper方法调用。
service{
//开始执行时,开启事务,创建SqlSession对象
//第一次调用mapper的方法findUserById(1)
//第二次调用mapper的方法findUserById(1),从一级缓存中取数据
//方法结束,sqlSession关闭
}
如果是执行两次service调用查询相同 的用户信息,不走一级缓存,因为session方法结束,sqlSession就关闭,一级缓存就清空。
二级缓存查询原理
二级缓存的应用场景
对于 访问多的查询请求且用户对于查询结果的实时性要求不高,此时可以采用mybatis 二级缓存来降低数据库的访问量,提高访问速度,业务场景包括 耗时较高的统计分析sql, 账单查询
实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。
mybatis 二级缓存的局限
mybatis二级缓存对细粒度的数据级别的缓存实现不好, 比如对于商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的 二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息(一个商品信息变化,二级缓存会将所有商品的信息从缓存中清除,非常不友好),因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。
开启二级缓存
- 默认情况下mybatis开启的是一级缓存,即是sqlSession级别的缓存
- 开启二级缓存分两步:
第一: 在SqlMapConfig.xml设置二级缓存的总开关
<setting name="cacheEnabled" value="true"/>
第二:在具体的mapper.xml中开启二级缓存.
<mapper namspace = "com.dustin.ssm.mapper">
<!-- 开启二级缓存-->
<cache/>
</mapper>
另外需要注意的是,因为二级缓存在内存中的存储介质多种多样,为了将缓存数据取出执行反序列化操作,需要将类实现序列化接口
如果开启了二级缓存,但是其中的一条sql语句每次都要查询最新数据怎么办? 不怕,mybatis 提供了useCache配置,可以针对某一条sql语句,禁用二级缓存功能。
在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
总结:针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存。
mybatis 的缓存与其他分布式缓存框架整合(ehcache,redis,mongdb)
mybatis 对缓存的支持并不是很好,因为,mybatis并不是专门做缓存的,而是一个ORM框架
- 为什么需要分布式缓存服务
目前的系统为了提高并发性能,一般都对其做了分布式的部署,应用运行在一个服务器集群上面,那么如果不使用分布式缓存框架的话,那么缓存分别就是保存在自己的那台机器上面,不方便系统进行开发。
举个例子: 用户登录了系统,该请求分配到机器A登录,那么用户的登录信息缓存在机器A上面,如果下一次用户发起了一个请求,被分到了机器B上,但是B上并没有用户的登录信息,那么用户就需要再次登录一遍,这是极其不合理的,所以需要针对缓存进行集中管理。
如何与其他分布式框架整合
mybatis提供了一个cache接口,如果要实现自己的缓存逻辑,实现cache接口开发即可。
比如mybatis和ehcache整合,其他的也都是大同小异
1. 加入ehcache jar包
2. 配置mapper中cache中的type为ehcache对cache接口的实现类型。
<mapper namespace="cn.itcast.ssm.mapper.UserMapper">
<!-- 开启mapper下的二级缓存,
type: 指定cache接口的实现类型,与谁整合就配置谁的接口, 例如与ehcache整合需要配置type 为ehcache实现的cache接口的类型
-->
<cache type = org.mybatis.caches.ehcache.EhcacheCache"/>
</mapper>
3 在classpath下加入ehcache的配置文件 ehcache.xml