1. Mybatis提供了查询缓存的功能,用于减轻数据库查询压力,分别提供了一级缓存和二级缓存两种缓存级别。java
2. 查询缓存,就是将SQL查询语句查询的结果缓存中内存中(经过HashMap保存),若是屡次执行同一个查询语句,就不须要每次都与数据库进行一次会话(建立SqlSeesion对象发送SQL语句),而是直接从内存中取出查询的结果,这样就能够提升性能,减小数据库压力。mysql
3. 一级缓存是SqlSession级别的缓存。在操做数据库时须要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不一样的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。spring
4. 二级缓存是mapper级别的缓存,多个SqlSession去操做同一个Mapper的sql语句,多个SqlSession能够共用二级缓存,二级缓存是跨SqlSession的。sql
1. 工做原理:以查询用户为例,数据库
2. Mybatis默认开启一级缓存,因此不须要进行配置操做。apache
3. 应用:缓存
在正式开发中,是将mybatis和spring进行整合开发,事务控制在service中。 一个service方法中包括 不少mapper方法调用。 service(){ //开始执行时,开启事务,建立SqlSession对象 //第一次调用mapper的方法findUserById(1) //第二次调用mapper的方法findUserById(1),从一级缓存中取数据 //方法结束,sqlSession关闭 } 若是是执行两次service调用查询相同 的用户信息,不走一级缓存,由于session方法结束,sqlSession就关闭,一级缓存就清空。
1. 工做原理:首先要开启二级缓存session
2. 二级缓存与一级缓存区别:二级缓存的范围更大,多个sqlSession能够共享一个UserMapper的二级缓存区域;其次二级缓存的位置不必定是内存中,也有多是硬盘或者其余缓存介质。UserMapper有一个二级缓存区域(按namespace分) ,其它mapper也有本身的二级缓存区域(按namespace分)。每个namespace的mapper都有一个二缓存区域,两个mapper的namespace若是相同,这两个mapper执行sql查询到数据将存在相同 的二级缓存区域中。数据结构
3. 配置开启二级缓存:首先在Mybatis的启动配置文件SqlMapConfig.xml中加入<setting name="cacheEnabled" value="true"/> ,而后在要开启二级缓存的Mapper映射文件中添加<cache></cache> 标签mybatis
<!--启动配置文件--> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> <!--开启二级缓存--> <setting name="cacheEnabled" value="true"/> </settings> <environments default="environment"> <environment id="environment"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/cloud_note?useUnicode=true&characterEncoding=utf8" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <!--指定映射文件位置--> <mappers> <mapper resource="mapper/Usermapper.xml"/> </mappers> </configuration> <!--Mapper文件配置--> <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="dao.UserDao"> <!--开启二级缓存--> <cache></cache> <select id="findUserById" parameterType="string" resultType="entity.User"> select * from cn_user where cn_user_id=#{id} </select> </mapper>
4. 禁用某SQL查询语句的二级缓存:在statement中设置useCache=false能够禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认值是true,即该sql使用二级缓存。<select id="find" resultMap="UserMap" useCache="false">;针对每次查询都须要最新的数据sql,要设置成useCache=false,禁用二级缓存。
5. 刷新缓存:在mapper的同一个namespace中,若是有其它insert、update、delete操做数据后须要刷新缓存,若是不执行刷新缓存会出现脏读。设置statement配置中的flushCache="true" 属性,默认值为true即刷新缓存,若是改为false则不会刷新。使用缓存时若是手动修改数据库表中的查询数据会出现脏读。<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">,通常都应该设置为true
1. Mybatis中的二级缓存不支持分布式缓存,要实现分布式缓存须要与第三方缓存工具进行整合使用,经常使用的好比Redis、ehcache等。
2. 整合原理:mybatis提供了一个Cache接口, 若是要实现本身的缓存逻辑,实现cache接口开发便可。
import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; public class MyCache implements Cache{ @Override public String getId() { return null; } @Override public void putObject(Object key, Object value) { } @Override public Object getObject(Object key) { return null; } @Override public Object removeObject(Object key) { return null; } @Override public void clear() { } @Override public int getSize() { return 0; } @Override public ReadWriteLock getReadWriteLock() { return null; } }
Mybatis默认使用的Cache实现类(实现二级缓存):使用HashMap实现
package org.apache.ibatis.cache.impl; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import org.apache.ibatis.cache.Cache; import org.apache.ibatis.cache.CacheException; public class PerpetualCache implements Cache { private String id; private Map<Object, Object> cache = new HashMap<Object, Object>(); public PerpetualCache(String id) { this.id = id; } public String getId() { return id; } public int getSize() { return cache.size(); } public void putObject(Object key, Object value) { cache.put(key, value); } public Object getObject(Object key) { return cache.get(key); } public Object removeObject(Object key) { return cache.remove(key); } public void clear() { cache.clear(); } public ReadWriteLock getReadWriteLock() { return null; } public boolean equals(Object o) { if (getId() == null) throw new CacheException("Cache instances require an ID."); if (this == o) return true; if (!(o instanceof Cache)) return false; Cache otherCache = (Cache) o; return getId().equals(otherCache.getId()); } public int hashCode() { if (getId() == null) throw new CacheException("Cache instances require an ID."); return getId().hashCode(); } }
除此以外提供了多种缓存策略的实现类:
3. 配置使用第三方缓存工具:以mybatis和ehcache整合包中提供了一个cache接口的实现类为例,
4. 二级缓存应用场景:对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术下降数据库访问量,提升访问速度,业务场景好比:耗时较高的统计分析sql、电话帐单查询sql等。由于若是要求查询结果数据实时性高,那么仍然会频繁的与数据进行交互,二级缓存就是去了意义;经过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,好比设置为30分钟、60分钟、24小时等,根据需求而定,在Mapper映射文件中的<cache>标签指定flushInterval属性的值便可,如<cache flushInterval="6000"></cache>,单位为毫秒