MyBatis-24MyBatis缓存配置【集成EhCache】

简介: MyBatis-24MyBatis缓存配置【集成EhCache】

20191208100305354.png



概述


Spring Cache抽象-基于XML的配置声明(基于EhCache的配置)

Spring Cache抽象-使用Java类注解的方式整合EhCache


EhCache概述


官方网站: http://www.ehcache.org/


Ehcache是一个用Java实现的使用简单,高速,实现线程安全的缓存管理类库,ehcache提供了用内存,磁盘文件存储,以及分布式存储方式等多种灵活的cache管理方案。


Ehcache 从 Hibernate 发展而来,逐渐涵盖了 Cahce 界的全部功能,是目前发展势头最好的一个项目。具有快速,简单,低消耗,依赖性小,扩展性强,支持对象或序列化缓存,支持缓存或元素的失效,提供 LRU、LFU 和 FIFO 缓存策略,支持内存缓存和磁盘缓存,分布式缓存机制等等特点。


特点


  • 快速
  • 简单
  • 多种缓存策略
  • 缓存数据有两级:内存和磁盘,因此无需担心容量问题
  • 缓存数据会在虚拟机重启的过程中写入磁盘
  • 可以通过 RMI、可插入 API 等方式进行分布式缓存
  • 具有缓存和缓存管理器的侦听接口
  • 支持多缓存管理器实例,以及一个实例的多个缓存区域
  • 提供 Hibernate 的缓存实现


EhCache架构图


20180508035236263.png


  • CacheManager:是缓存管理器,可以通过单例或者多例的方式创建,Ehcache的入口类。
  • Cache:每个CacheManager可以管理多个Cache,每个Cache可以采用hash的方式管理多个Element。
  • Element:用于存放真正缓存内容的。


示例

1.添加mybatis-ehcache依赖

<properties>
  .....
  <mybatis-ehcache.version>1.0.3</mybatis-ehcache.version>
</properties>
<dependencies>
  ......
  <dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>${mybatis-ehcache.version}</version>
  </dependency>
</dependencies>



2. 配置EhCache

在src/main/resources 目录下 新建ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="ehcache.xsd"
    updateCheck="false" 
    monitoring="autodetect"
    dynamicConfig="true">
    <diskStore path="D:/cache" />
  <defaultCache      
    maxElementsInMemory="3000"      
    eternal="false"      
    copyOnRead="true"
    copyOnWrite="true"
    timeToIdleSeconds="3600"      
    timeToLiveSeconds="3600"      
    overflowToDisk="true"      
    diskPersistent="true"/> 
</ehcache>


关于EhCache配置文件参考官网配置

http://www.ehcache.org/ehcache.xml

属性解读


copyOnRead:判断从缓存中读取数据时是返回对象的引用还是复制一个对象返回。 默认false,即返回数据的引用。 这种情况下返回的都是相同的对象,和MyBatis默认缓存中的只读对象是相同的。 如果设置为true,那就是可读可写缓存,每次读取缓存都会复制一个新的实例


copyOnWrite:判断写入缓存时是直接缓存对象的引用还是复制一个对象然后缓存。 默认也是false。如果想使用可读可写缓存,就需要将这两个属性配置为true。 如果使用只读缓存,可以不配置这两个属性,使用默认false即可。


3.修改PrivilegeMapper.xml中的缓存配置

<?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接口和XML文件关联的时候, namespace的值就需要配置成接口的全限定名称 -->
<mapper namespace="com.artisan.mybatis.xml.mapper.PrivilegeMapper">
  <!-- 在全局配置文件开启二级缓存的前提下,给Privilege开启二级缓存,使用默认配置
    <cache/>
   -->
  <!-- 集成EhCache缓存  -->
  <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
  <resultMap id="privilegeMap" type="com.artisan.mybatis.xml.domain.SysPrivilege">
    <id property="id" column="id" />
    <result property="privilegeName" column="privilege_name" />
    <result property="privilegeUrl" column="privilege_url" />
  </resultMap>
  <select id="selectPrivilegeByIdWithCache"  resultType="com.artisan.mybatis.xml.domain.SysPrivilege">
    SELECT
      id,
      privilege_name privilegeName,
      privilege_url privilegeUrl
    FROM
      sys_privilege
    WHERE
      id = #{id}
  </select>
</mapper>       


e h c a c h e - c a c h e提供如下2个可选的缓存实现


20180508075351804.png


并没有什么区别,都会输出缓存命中率的日志


只需要设置type属性就可以使用EhCache缓存了,这时候cache的其他属性都不会起作用,这对缓存的配置都在ehcache.xml中进行。


在ehcache.xml中只有一个默认的缓存配置,所以配置使用EhCache缓存的Mapper映射文件都会有一个以映射文件命令空间命名的缓存。 如果想针对某一个命名空间配置,需要在ehcache.xml中添加一个和映射文件命名空间一致的缓存配置。比如针对PrivilegeMapper

<cache      
    name="com.artisan.mybatis.xml.mapper.PrivilegeMapper"
    maxElementsInMemory="3000"      
    eternal="false"      
    copyOnRead="true"
    copyOnWrite="true"
    timeToIdleSeconds="3600"      
    timeToLiveSeconds="3600"      
    overflowToDisk="true"      
    diskPersistent="true"/> 


4.单元测试

@Test
  public void selectPrivilegeByIdWithCacheTest() {
    logger.info("selectPrivilegeByIdWithCacheTest");
    SqlSession sqlSession =  getSqlSession();
    SysPrivilege sysPrivilege = null;
    try {
      // 获取接口
      PrivilegeMapper privilegeMapper = sqlSession.getMapper(PrivilegeMapper.class);
      // 调用接口方法
      sysPrivilege = privilegeMapper.selectPrivilegeByIdWithCache(1L);
      sysPrivilege.setPrivilegeName("New Priv");
      // 再次调用相同的接口方法,查询相同的用户
      logger.info("再次调用相同的接口方法,查询相同的用户 Begin");
      SysPrivilege sysPrivilege2 = privilegeMapper.selectPrivilegeByIdWithCache(1L);
      logger.info("再次调用相同的接口方法,查询相同的用户 End");
      // 一级缓存在同一个sqlSession中,虽然没有更新数据库,但是会使用一级缓存
      Assert.assertEquals("New Priv", sysPrivilege2.getPrivilegeName());
      // sysPrivilege 和 sysPrivilege2 是同一个实例
      Assert.assertEquals(sysPrivilege, sysPrivilege2);
    } finally {
      // sqlSession关闭后,在二级缓存开启的前提下,会写入二级缓存
      sqlSession.close();
    }
    logger.info("重新获取一个SqlSession");
    sqlSession = getSqlSession();
    try {
      // 获取接口
      PrivilegeMapper privilegeMapper = sqlSession.getMapper(PrivilegeMapper.class);
      // 调用接口方法
      SysPrivilege sysPrivilege2 = privilegeMapper.selectPrivilegeByIdWithCache(1L);
      sysPrivilege.setPrivilegeName("New Priv");
      // 第二个session获取的权限名为 New Priv
      Assert.assertEquals("New Priv", sysPrivilege2.getPrivilegeName());
      // 这里的sysPrivilege2 和 前一个session中的sysPrivilege不是同一个实例
      Assert.assertNotEquals(sysPrivilege, sysPrivilege2);
      // 获取sysPrivilege3
      SysPrivilege sysPrivilege3 = privilegeMapper.selectPrivilegeByIdWithCache(1L);
      // 这里的sysPrivilege2 和sysPrivilege3是两个不同的实例
      Assert.assertNotEquals(sysPrivilege2, sysPrivilege3);
    } finally {
      // sqlSession关闭后,在二级缓存开启的前提下,会写入二级缓存
      sqlSession.close();
    }
  }


日志

2018-05-07 19:58:27,653  INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully
2018-05-07 19:58:27,656  INFO [main] (BaseMapperTest.java:29) - reader close successfully
2018-05-07 19:58:27,659  INFO [main] (PrivilegeMapperTest.java:38) - selectPrivilegeByIdWithCacheTest
2018-05-07 19:58:27,682 DEBUG [main] (LoggingCache.java:62) - Cache Hit Ratio [com.artisan.mybatis.xml.mapper.PrivilegeMapper]: 0.0
2018-05-07 19:58:27,743 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT id, privilege_name privilegeName, privilege_url privilegeUrl FROM sys_privilege WHERE id = ? 
2018-05-07 19:58:27,855 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: 1(Long)
2018-05-07 19:58:27,886 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, privilegeName, privilegeUrl
2018-05-07 19:58:27,887 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, 用户管理, /users
2018-05-07 19:58:27,890 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
2018-05-07 19:58:27,892  INFO [main] (PrivilegeMapperTest.java:48) - 再次调用相同的接口方法,查询相同的用户 Begin
2018-05-07 19:58:27,892 DEBUG [main] (LoggingCache.java:62) - Cache Hit Ratio [com.artisan.mybatis.xml.mapper.PrivilegeMapper]: 0.0
2018-05-07 19:58:27,893  INFO [main] (PrivilegeMapperTest.java:50) - 再次调用相同的接口方法,查询相同的用户 End
2018-05-07 19:58:27,923  INFO [main] (PrivilegeMapperTest.java:60) - 重新获取一个SqlSession
2018-05-07 19:58:27,927 DEBUG [main] (LoggingCache.java:62) - Cache Hit Ratio [com.artisan.mybatis.xml.mapper.PrivilegeMapper]: 0.3333333333333333
2018-05-07 19:58:27,928 DEBUG [main] (LoggingCache.java:62) - Cache Hit Ratio [com.artisan.mybatis.xml.mapper.PrivilegeMapper]: 0.5


相关文章
|
3月前
|
缓存 Java 数据库连接
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
文章介绍了MyBatis的缓存机制,包括一级缓存和二级缓存的配置和使用,以及如何整合第三方缓存EHCache。详细解释了一级缓存的生命周期、二级缓存的开启条件和配置属性,以及如何通过ehcache.xml配置文件和logback.xml日志配置文件来实现EHCache的整合。
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
|
21天前
|
缓存 Java 数据库连接
MyBatis缓存机制
MyBatis提供两级缓存机制:一级缓存(Local Cache)默认开启,作用范围为SqlSession,重复查询时直接从缓存读取;二级缓存(Second Level Cache)需手动开启,作用于Mapper级别,支持跨SqlSession共享数据,减少数据库访问,提升性能。
27 1
|
24天前
|
缓存 Java 数据库连接
深入探讨:Spring与MyBatis中的连接池与缓存机制
Spring 与 MyBatis 提供了强大的连接池和缓存机制,通过合理配置和使用这些机制,可以显著提升应用的性能和可扩展性。连接池通过复用数据库连接减少了连接创建和销毁的开销,而 MyBatis 的一级缓存和二级缓存则通过缓存查询结果减少了数据库访问次数。在实际应用中,结合具体的业务需求和系统架构,优化连接池和缓存的配置,是提升系统性能的重要手段。
39 4
|
1月前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
1月前
|
存储 缓存 安全
在 Service Worker 中配置缓存策略
Service Worker 是一种可编程的网络代理,允许开发者控制网页如何加载资源。通过在 Service Worker 中配置缓存策略,可以优化应用性能,减少加载时间,提升用户体验。此策略涉及缓存的存储、更新和检索机制。
|
1月前
|
SQL 缓存 Java
MyBatis如何关闭一级缓存(分注解和xml两种方式)
MyBatis如何关闭一级缓存(分注解和xml两种方式)
79 5
|
1月前
|
存储 缓存 监控
配置 Webpack 5 持久化缓存时需要注意哪些安全问题?
【10月更文挑战第23天】通过全面、系统地分析和应对安全问题,能够更好地保障 Webpack 5 持久化缓存的安全,为项目的成功构建和运行提供坚实的安全基础。同时,要保持对安全技术的关注和学习,不断提升安全防范能力,以应对日益复杂的安全挑战。
|
2月前
|
缓存 Java 数据库连接
使用MyBatis缓存的简单案例
MyBatis 是一种流行的持久层框架,支持自定义 SQL 执行、映射及复杂查询。本文介绍了如何在 Spring Boot 项目中集成 MyBatis 并实现一级和二级缓存,以提高查询性能,减少数据库访问。通过具体的电商系统案例,详细讲解了项目搭建、缓存配置、实体类创建、Mapper 编写、Service 层实现及缓存测试等步骤。
|
2月前
|
存储 缓存 监控
|
3月前
|
SQL XML Java
mybatis复习01,简单配置让mybatis跑起来
文章介绍了MyBatis的基本概念、历史和特点,并详细指导了如何配置MyBatis环境,包括创建Maven项目、添加依赖、编写核心配置文件、创建数据表和实体类、编写Mapper接口和XML配置文件,以及如何编写工具类和测试用例。
mybatis复习01,简单配置让mybatis跑起来