您的位置:首页 > 其它

MyBatis 缓存机制

2017-11-06 22:43 323 查看

1. 概述

1.1 缓存可以极大的提升查询效率,MyBatis 系统中默认定义了两级缓存:一级缓存和二级缓存
  • 默认情况下,只有一级缓存(SqlSession 级别的缓存,也称为本地缓存)开启;
  • 二级缓存(基于namespace 级别的缓存, 也称为全局缓存)需要手动开启和配置;
  • 为了提高扩展性,MyBatis 定义了缓存接口 Cache, 可以通过实现Cache 接口来自定义二级缓存;

2. 一级缓存

  • 一级缓存: 与数据库同一次会话期间,查询到的数据会放在本地缓存中;以后,如果需要获取相同的数据,直接从缓存中获取;
  • 一级缓存就是SqlSession级别的一个Map;
  • 一级缓存失效的情况(即获取相同的数据,需要发送两次sql语句) SqlSession 不同时,一级缓存失效;
  • SqlSession 相同,查询条件不同;
  • SqlSession 相同,但是两次查询之间,执行了增删改操作;
  • SqlSession 相同,手动清除了一级缓存;(
    clearCache()
    方法)
// EmployeeMapper.java
public class EmployeeMapper{

public Employee getEmpById(Integer id);
}

// EmployeeMapper.xml
<resultMap type="cn.itcast.mybatis.bean.Employee" id="MyEmp">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
</resultMap>

<select id="getEmpById" resultMap="MyEmp">
select * from tbl_employee where id=#{id}
</select>

// 测试类
public class MyTest{

@Test
public void test01 throw IOException{
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();

SqlSession openSession = sqlSessionFactory.openSession();

try{
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);

// 一级缓存
Employee emp01 = mapper.getEmpById(1);
System.out.println(emp01);

Employee emp02 = mapper.getEmpById(1);
System.out.println(emp02);
System.out.println(emp01==emp02);

}finally{
openSession.close();
}
}
}

3. 二级缓存

  1. 基于namespace级别的缓存,一个namespace对应一个二级缓存;
  2. 查询出的数据,都会默认放在一级缓存中,只有会话提交或关闭之后,一级缓存中的数据才会转移到二级缓存;
  3. 工作机制:
      一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
    • 如果会话关闭,一级缓存中的数据会被保存到二级缓存中; 新的会话查询信息,就可以参照二级缓存中的内容;
    • 例如,使用EmployeeMapper对象,查询到的Employee对象, 和使用DepartmentMapper对象,查询到
      的Department对象分别存放在不同的map中;即不同namespace查询出的数据,会放在自己对应的缓存(map);
  4. 使用步骤:
      mybatis-config.xml
      中开启:
      <setting name="cacheEnabled" value="true"/>
      ;
    • xxxMapper.xml
      中配置使用二级缓存:
      <cache></cache>
      ,常用属性:
      eviction
      : 缓存的回收策略;(LRU, FIFO, SOFT, WEAK)
    • flushInterval
      : 缓存刷新间隔; 即缓存多长时间清空一次,默认不清空;
    • readOnly
      : 缓存是否只读;
    • size
      : 缓存存放多少元素;
    • type
      : 指定自定义缓存的全类名;
  5. POJO 需要实现序列化接口;
  6. 和缓存相关的设置/属性:
      cacheEnabled=false
      : 关闭的是二级缓存,一级缓存仍可用;
    • select 标签中的
      useCache=false
      : 关闭的也是二级缓存,一级缓存依然可以使用;
    • 每个增删改标签都存在
      flushCache=true
      ,默认为true; 表示增删改执行完成后,就会清空一级缓存和二级缓存;
    • 查询标签的
      fluseCache
      的属性默认为 false;
    • sqlSession.clearCache()
      : 只清空当前session中的一级缓存;
// 测试类
public class MyTest{

@Test
public void test01 throw IOException{
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();

SqlSession openSession = sqlSessionFactory.openSession();
SqlSession openSession2 = sqlSessionFactory.openSession();

try{
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class);

// 两次会话,查询内容相同; 二级缓存开启的情况下,只会发送一条SQL语句
Employee emp01 = mapper.getEmpById(1);
System.out.println(emp01);
openSession.close();

Employee emp02 = mapper2.getEmpById(1);
System.out.println(emp02);
openSession2.close();

}finally{

}
}
}

4. 整合第三方缓存(ehcache)

  1. 导入jar包:
    ehcache-core-2.6.8
    ,
    slf4j-api
    ,
    slf4j-log4j
    ,
    mybatis-ehcache
    ;
  2. 配置 EmployeeMapper.xml
  3. 在类路径下新建
    ehcache.xml
    文件
// EmployeeMapper.xml
<mapper namespace="cn.itcast.mybatis.dao.EmployeeMapper">

<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

<resultMap type="cn.itcast.mybatis.bean.Employee" id="MyEmp">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
</resultMap>

<select id="getEmpById" resultMap="MyEmp">
select * from tbl_employee where id=#{id}
</select>
</mapper>

// DepartmentMapper.xml
<mapper namespace="cn.itcast.mybatis.dao.DepartmentMapper">

<!-- 引用缓存: namespace,指定和哪个名称空间下的缓存一样 -->
<cache-ref namespace="cn.itcast.mybatis.dao.EmployeeMapper"/>

<resultMap type="cn.itcast.mybatis.bean.Employee" id="MyEmp">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
</resultMap>

<select id="getEmpById" resultMap="MyEmp">
select * from tbl_employee where id=#{id}
</select>
</mapper>


参考资料

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: