第一章:Mybatis 的缓存机制介绍

  • Mybatis 包含了一个非常强大的查询缓存特性,它可以非常方便的配置和定制。缓存可以极大的提升查询效率。
  • Mybatis 系统中默认定义了两级缓存:一级缓存和二级缓存。
    • 默认情况下,只有一级缓存(SqlSession 级别的缓存,也称为本地缓存)开启。
    • 二级缓存需要手动开启和配置,它是基于 namespace 级别的缓存。
    • 为了提高扩展性。Mybatis 定义了缓存接口 Cache 。我们可以通过实现 Cache 接口来自定义二级缓存。

第二章:准备工作

  • 导入相关 jar 包的 Maven 坐标:
  1. <dependency>
  2. <groupId>org.mybatis</groupId>
  3. <artifactId>mybatis</artifactId>
  4. <version>3.4.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>log4j</groupId>
  8. <artifactId>log4j</artifactId>
  9. <version>1.2.17</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>mysql</groupId>
  13. <artifactId>mysql-connector-java</artifactId>
  14. <version>8.0.21</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>junit</groupId>
  18. <artifactId>junit</artifactId>
  19. <version>4.13</version>
  20. <scope>test</scope>
  21. </dependency>
  • sql 脚本
  1. DROP TABLE IF EXISTS `employee`;
  2. CREATE TABLE `employee` (
  3. `id` int(11) NOT NULL AUTO_INCREMENT,
  4. `last_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  5. `gender` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  6. `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  7. PRIMARY KEY (`id`) USING BTREE
  8. ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
  • db.properties
  1. jdbc.url=jdbc:mysql://192.168.134.100:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&allowMultiQueries=true
  2. jdbc.driverClass=com.mysql.cj.jdbc.Driver
  3. jdbc.username=root
  4. jdbc.password=123456
  • log4j.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
  3. <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  4. <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
  5. <param name="Encoding" value="UTF-8" />
  6. <layout class="org.apache.log4j.PatternLayout">
  7. <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
  8. </layout>
  9. </appender>
  10. <logger name="java.sql">
  11. <level value="debug" />
  12. </logger>
  13. <logger name="org.apache.ibatis">
  14. <level value="info" />
  15. </logger>
  16. <root>
  17. <level value="debug" />
  18. <appender-ref ref="STDOUT" />
  19. </root>
  20. </log4j:configuration>
  • Employee.java
  1. package com.sunxiaping.domain;
  2. import org.apache.ibatis.type.Alias;
  3. import java.io.Serializable;
  4. @Alias("emp")
  5. public class Employee implements Serializable {
  6. private Integer id;
  7. private String lastName;
  8. private String email;
  9. private String gender;
  10. public Integer getId() {
  11. return id;
  12. }
  13. public void setId(Integer id) {
  14. this.id = id;
  15. }
  16. public String getLastName() {
  17. return lastName;
  18. }
  19. public void setLastName(String lastName) {
  20. this.lastName = lastName;
  21. }
  22. public String getEmail() {
  23. return email;
  24. }
  25. public void setEmail(String email) {
  26. this.email = email;
  27. }
  28. public String getGender() {
  29. return gender;
  30. }
  31. public void setGender(String gender) {
  32. this.gender = gender;
  33. }
  34. @Override
  35. public String toString() {
  36. return "Employee{" +
  37. "id=" + id +
  38. ", lastName='" + lastName + '\'' +
  39. ", email='" + email + '\'' +
  40. ", gender='" + gender + '\'' +
  41. '}';
  42. }
  43. }
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. public interface EmployeeMapper {
  3. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. </mapper>
  • mybatis-config.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <properties resource="db.properties"></properties>
  7. <settings>
  8. <!-- 开启自动驼峰命名规则映射 -->
  9. <setting name="mapUnderscoreToCamelCase" value="true"/>
  10. <!-- 开启对jdbcType的NULL的支持 -->
  11. <setting name="jdbcTypeForNull" value="NULL"/>
  12. <!-- 开启延迟加载 -->
  13. <setting name="lazyLoadingEnabled" value="true"/>
  14. <!-- 开启按需加载 -->
  15. <setting name="aggressiveLazyLoading" value="false"/>
  16. </settings>
  17. <environments default="development">
  18. <environment id="development">
  19. <transactionManager type="JDBC"/>
  20. <dataSource type="POOLED">
  21. <property name="driver" value="${jdbc.driverClass}"/>
  22. <property name="url" value="${jdbc.url}"/>
  23. <property name="username" value="${jdbc.username}"/>
  24. <property name="password" value="${jdbc.password}"/>
  25. </dataSource>
  26. </environment>
  27. </environments>
  28. <mappers>
  29. <package name="com.sunxiaping.mapper"/>
  30. </mappers>
  31. </configuration

第三章:一级缓存

3.1 一级缓存体验

  • 和数据库同一次会话期间查询到的数据会放在本地缓存中,如果以后需要获取相同的数据,直接从缓存中取,而不需要再去查询数据库。

  • 示例:

  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. public interface EmployeeMapper {
  4. Employee findById(Integer id);
  5. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <!--
  7. 抽取可重用的SQL片段,方便后面引用
  8. -->
  9. <sql id="emp_sql" >
  10. id as id,last_name as lastName,email as email ,gender as gender
  11. </sql>
  12. <select id="findById" resultType="com.sunxiaping.domain.Employee">
  13. SELECT <include refid="emp_sql"/>
  14. FROM employee
  15. WHERE id = #{id,jdbcType=INTEGER}
  16. </select>
  17. </mapper>
  • 测试:
  1. package com.sunxiaping;
  2. import com.sunxiaping.domain.Employee;
  3. import com.sunxiaping.mapper.EmployeeMapper;
  4. import org.apache.ibatis.io.Resources;
  5. import org.apache.ibatis.session.SqlSession;
  6. import org.apache.ibatis.session.SqlSessionFactory;
  7. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  8. import org.junit.After;
  9. import org.junit.Before;
  10. import org.junit.Test;
  11. import java.io.IOException;
  12. import java.io.InputStream;
  13. public class EmployeeTest {
  14. SqlSessionFactory sqlSessionFactory = null;
  15. SqlSession sqlSession = null;
  16. EmployeeMapper employeeMapper = null;
  17. @Before
  18. public void before() throws IOException {
  19. String resource = "mybatis-config.xml";
  20. InputStream inputStream = Resources.getResourceAsStream(resource);
  21. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  22. sqlSession = sqlSessionFactory.openSession(true);
  23. employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
  24. }
  25. @After
  26. public void after() {
  27. if (null != sqlSession) {
  28. sqlSession.close();
  29. }
  30. }
  31. @Test
  32. public void testFindById() {
  33. Employee employee1 = employeeMapper.findById(1);
  34. Employee employee2 = employeeMapper.findById(1);
  35. System.out.println(employee1 == employee2);
  36. }
  37. }
  • 日志:

一级缓存体验日志.jpg

3.2 一级缓存失效的四种情况

  • ① SqlSession不同,一级缓存不同。
  • ② SqlSession相同,但是查询条件不同(当前一级缓存中还没有这个数据),一级缓存不同。
  • ③ SqlSession相同,两次查询期间执行了增删改操作(这次增删改可能对当前数据有影响),一级缓存不同。
  • ④ SqlSession相同,手动清空了缓存,一级缓存不同。

第四章:二级缓存

4.1 二级缓存的介绍

  • 基于 namespace 级别的缓存,一个 namespace 对应一个二级缓存。
  • 工作机制:
    • ① 一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中;
    • ② 如果会话关闭,一级缓存中的数据会被保存到二级缓存中。
    • ③ 新的会话查询信息,就可以参照二级缓存。
    • ④ 对于一个 SqlSession 来说,如果通过 EmployeeMapper 查询到 Employee 对象,和通过 DepartmentMapper 查询到 Department 对象,放到二级缓存中的位置是不同的。

4.2 二级缓存的使用

  • 步骤:

    • ① 全局配置文件中开启二级缓存。

      1. <settings>
      2. <!-- 开启自动驼峰命名规则映射 -->
      3. <setting name="mapUnderscoreToCamelCase" value="true"/>
      4. <!-- 开启对jdbcType的NULL的支持 -->
      5. <setting name="jdbcTypeForNull" value="NULL"/>
      6. <!-- 开启延迟加载 -->
      7. <setting name="lazyLoadingEnabled" value="true"/>
      8. <!-- 开启按需加载 -->
      9. <setting name="aggressiveLazyLoading" value="false"/>
      10. <!-- 开启二级缓存 -->
      11. <setting name="cacheEnabled" value="true"/>
      12. </settings>
    • ② 需要在使用二级缓存的映射文件处使用 cache 配置缓存。

      1. <!--
      2. cache标签:配置缓存的相关属性
      3. - evication:缓存回收策略
      4. - LRU:最近最少使用的,移除最长时间不被使用的对象,默认值。
      5. - FIFO:先进先出,按对象进入缓存的顺序来移出它们。
      6. - SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象。
      7. - WEAK:弱引用,更积极的移除基于垃圾收集器状态和弱引用规则的对象。
      8. - flushInterval:刷新时间,单位是毫秒。
      9. - 缓存多长时间清空一次,默认不清空。
      10. - size:缓存存放多少元素,正整数。
      11. - readOnly:是否只读。
      12. - true:只读缓存。
      13. - Mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。
      14. - Mybatis为了加快获取速度,直接将数据在缓存中的引用交给用户。
      15. - 不安全,速度快。
      16. - false:读写缓存。
      17. - Mybatis认为获取的数据可能会被修改。
      18. - Mybatis会利用序列化&&反序列化的技术克隆一份新的数据给你。
      19. - 安全,速度慢。
      20. - type:指定自定义缓存的全类名。
      21. - 实现Cache接口即可
      22. -->
      23. <cache eviction="LRU" flushInterval="60000" readOnly="false" size="1024" />
    • ③ 注意 POJO 需要实现 java.io.Serializable 接口。

  • 示例:

  • mybatis-config.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <properties resource="db.properties"></properties>
  7. <settings>
  8. <!-- 开启自动驼峰命名规则映射 -->
  9. <setting name="mapUnderscoreToCamelCase" value="true"/>
  10. <!-- 开启对jdbcType的NULL的支持 -->
  11. <setting name="jdbcTypeForNull" value="NULL"/>
  12. <!-- 开启延迟加载 -->
  13. <setting name="lazyLoadingEnabled" value="true"/>
  14. <!-- 开启按需加载 -->
  15. <setting name="aggressiveLazyLoading" value="false"/>
  16. <!-- 开启二级缓存 -->
  17. <setting name="cacheEnabled" value="true"/>
  18. </settings>
  19. <environments default="development">
  20. <environment id="development">
  21. <transactionManager type="JDBC"/>
  22. <dataSource type="POOLED">
  23. <property name="driver" value="${jdbc.driverClass}"/>
  24. <property name="url" value="${jdbc.url}"/>
  25. <property name="username" value="${jdbc.username}"/>
  26. <property name="password" value="${jdbc.password}"/>
  27. </dataSource>
  28. </environment>
  29. </environments>
  30. <databaseIdProvider type="DB_VENDOR">
  31. <!--
  32. 为不同的数据库厂商起别名
  33. -->
  34. <property name="MySQL" value="mysql"/>
  35. <property name="Oracle" value="oracle"/>
  36. <property name="SQL Server" value="sqlserver"/>
  37. </databaseIdProvider>
  38. <mappers>
  39. <package name="com.sunxiaping.mapper"/>
  40. </mappers>
  41. </configuration>
  • EmployeeMapper.java
  1. package com.sunxiaping.mapper;
  2. import com.sunxiaping.domain.Employee;
  3. public interface EmployeeMapper {
  4. Employee findById(Integer id);
  5. }
  • EmployeeMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <!--
  7. cache标签:配置缓存的相关属性
  8. - evication:缓存回收策略
  9. - LRU:最近最少使用的,移除最长时间不被使用的对象,默认值。
  10. - FIFO:先进先出,按对象进入缓存的顺序来移出它们
  11. - SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象
  12. - WEAK:弱引用,更积极的移除基于垃圾收集器状态和弱引用规则的对象
  13. - flushInterval:刷新时间,单位是毫秒。
  14. - 缓存多长时间清空一次,默认不清空。
  15. - size:缓存存放多少元素,正整数。
  16. - readOnly:是否只读
  17. - true:只读缓存。
  18. - Mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。
  19. - Mybatis为了加快获取速度,直接将数据在缓存中的引用交给用户。
  20. - 不安全,速度快。
  21. - false:读写缓存。
  22. - Mybatis认为获取的数据可能会被修改。
  23. - Mybatis会利用序列化&&反序列化的技术克隆一份新的数据给你。
  24. - 安全,速度慢。
  25. - type:指定自定义缓存的全类名。
  26. - 实现Cache接口即可
  27. -->
  28. <cache eviction="LRU" flushInterval="60000" readOnly="false" size="1024"/>
  29. <sql id="emp_sql">
  30. id as id,last_name as lastName,email as email ,gender as gender
  31. </sql>
  32. <select id="findById" resultType="com.sunxiaping.domain.Employee">
  33. SELECT
  34. <include refid="emp_sql"/>
  35. FROM employee
  36. WHERE id = #{id,jdbcType=INTEGER}
  37. </select>
  38. </mapper>
  • 测试:
  1. package com.sunxiaping;
  2. import com.sunxiaping.domain.Employee;
  3. import com.sunxiaping.mapper.EmployeeMapper;
  4. import org.apache.ibatis.io.Resources;
  5. import org.apache.ibatis.session.SqlSession;
  6. import org.apache.ibatis.session.SqlSessionFactory;
  7. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
  8. import org.junit.Before;
  9. import org.junit.Test;
  10. import java.io.IOException;
  11. import java.io.InputStream;
  12. public class EmployeeTest {
  13. SqlSessionFactory sqlSessionFactory = null;
  14. @Before
  15. public void before() throws IOException {
  16. String resource = "mybatis-config.xml";
  17. InputStream inputStream = Resources.getResourceAsStream(resource);
  18. sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  19. }
  20. @Test
  21. public void testSecondLevelCache() {
  22. SqlSession sqlSession = sqlSessionFactory.openSession(true);
  23. SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
  24. EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
  25. EmployeeMapper employeeMapper2 = sqlSession2.getMapper(EmployeeMapper.class);
  26. Employee employee1 = employeeMapper.findById(1);
  27. System.out.println("employee1 = " + employee1);
  28. sqlSession.close();
  29. //第二次查询是从二级缓存中拿到的数据,并没有发送新的SQL
  30. Employee employee2 = employeeMapper2.findById(1);
  31. System.out.println("employee2 = " + employee2);
  32. sqlSession2.close();
  33. }
  34. }

4.3 缓存有关的设置和属性

  • 全局配置文件中的 cacheEache 如果设置为 false,将会关闭二级缓存;但是一级缓存一直打开。
  • Mapper 映射文件的每个 select 标签的都有 useCache 属性,如果设置为 false ,将会不使用二级缓存;但是一级缓存一直打开。
  • Mapper 映射文件中的 insert、delete、update 标签的 flushCache 属性,默认情况下是 true ,意味着执行之后将会清空一级缓存和二级缓存;而 select 标签的 flushcache 属性,默认情况下是 false ,不会清空一级缓存和二级缓存。
  • 调用 sqlSessio n的 clearCache() 方法只会清空一级缓存。
  • 全局配置文件中的 localCacheScope 默认值是 SESSION ,当前会话的所有数据保存在会话中。如果设置为 STATEMENT ,将禁用一级缓存。
  • 当在某一个作用域(一级缓存或二级缓存)进行了增删改操作后,默认情况下该作用域的所有 select 中的缓存将被清空。

4.4 缓存原理图

缓存原理.jpg

4.5 第三方缓存整合 Mybatis

4.5.1 Ehcache 概述

  • Ehcache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点,是 Hibernate 中默认的 CacheProvide r。
  • Mybatis 定义了 Cache 接口方便我们进行自定义扩展,而 mybatis-ehcache 就对Ehcache进行了整合。

4.5.2 Ehcache 整合 Mybatis 步骤

  • 导入 ehcache 包、mybatis-ehcache 的整合包以及日志包的 Maven 坐标:
  1. <dependency>
  2. <groupId>org.mybatis.caches</groupId>
  3. <artifactId>mybatis-ehcache</artifactId>
  4. <version>1.0.3</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.slf4j</groupId>
  8. <artifactId>slf4j-api</artifactId>
  9. <version>1.6.1</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.slf4j</groupId>
  13. <artifactId>slf4j-log4j12</artifactId>
  14. <version>1.6.1</version>
  15. <scope>test</scope>
  16. </dependency>
  • 编写 ehcache.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
  4. <!-- 磁盘保存路径 -->
  5. <diskStore path="D:\ehcache" />
  6. <defaultCache
  7. maxElementsInMemory="10000"
  8. maxElementsOnDisk="10000000"
  9. eternal="false"
  10. overflowToDisk="true"
  11. timeToIdleSeconds="120"
  12. timeToLiveSeconds="120"
  13. diskExpiryThreadIntervalSeconds="120"
  14. memoryStoreEvictionPolicy="LRU">
  15. </defaultCache>
  16. </ehcache>
  17. <!--
  18. 属性说明:
  19. diskStore:指定数据在磁盘中的存储位置。
  20. defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
  21. 以下属性是必须的:
  22. maxElementsInMemory - 在内存中缓存的element的最大数目
  23. maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
  24. eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
  25. overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
  26. 以下属性是可选的:
  27. timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
  28. timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
  29. diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
  30. diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
  31. diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
  32. memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
  33. -->
  • 在 Mapper 的映射文件中配置 cache 标签
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.EmployeeMapper">
  6. <!--
  7. 配置Ehcache缓存
  8. -->
  9. <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
  10. <sql id="emp_sql">
  11. id as id,last_name as lastName,email as email ,gender as gender
  12. </sql>
  13. <select id="findById" resultType="com.sunxiaping.domain.Employee">
  14. SELECT
  15. <include refid="emp_sql"/>
  16. FROM employee
  17. WHERE id = #{id,jdbcType=INTEGER}
  18. </select>
  19. </mapper>

4.5.3 参照缓存

  • 如果想在命名空间中共享相同的缓存配置和示例,可以使用 cache-ref 标签来引用另外一个缓存。

  • 示例:

  • DepartmentMapper.xml
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.sunxiaping.mapper.DepartmentMapper">
  6. <!-- 参照缓存 -->
  7. <cache-ref namespace="com.sunxiaping.mapper.EmployeeMapper"/>
  8. </mapper>

4.6 Tomcat 、二级缓存 、HttpSession 、HttpServletReqeust 和 SqlSession(事务)之间的关系

Tomcat、二级缓存、请求、SqlSession之间的关系.jpg