zoukankan      html  css  js  c++  java
  • 9.Mybatis缓存

    转载:https://blog.kuangstudy.com/index.php/archives/508/

    一.缓存

    1.简介

    1. 什么是缓存 [ Cache ]?

      • 存在内存中的临时数据。

      • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。

    2. 为什么使用缓存?

      • 减少和数据库的交互次数,减少系统开销,提高系统效率。

    3. 什么样的数据能使用缓存?

      • 经常查询并且不经常改变的数据

    2.Mybatis缓存

    • MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。

    • MyBatis系统中默认定义了两级缓存:一级缓存二级缓存

      • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)

      • 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。

      • 为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存

    3.一级缓存

    • 一级缓存也叫本地缓存:

      • 与数据库同一次会话期间查询到的数据会放在本地缓存中。

      • 以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;

    (1)搭建项目mybatis_cache

    UserMapper.java接口:

    1 //根据ID查询用户
    2 User queryById(@Param("id") int id);

    UserMapper.xml:

    1 <select id="queryById" parameterType="_int" resultType="User">
    2     select * from mybatis.user where id = #{id};
    3 </select>

    测试代码:

     1 @Test
     2 public void queryByIdTest(){
     3     SqlSession session = MybatisUtils.getSession();
     4 
     5     UserMapper mapper = session.getMapper(UserMapper.class);
     6 
     7     User user = mapper.queryById(1);
     8     System.out.println(user);
     9 
    10     System.out.println("=====================");
    11 
    12     User user2 = mapper.queryById(1);
    13     System.out.println(user2);
    14 
    15     session.close();
    16 }

    查看日志输出结果:

    分析日志:

    • 可以从日志看出只执行一次查询,第二个查询语句使用了缓存

    (2)缓存失效情况(4种情况)

    1. 查询不同东西

    2. 增删改操作,可能改变原来的数据,所以必定会刷新缓存!

    3. 查询不同的Mapper.xml

    4. 手动清理缓存!

       1 @Test
       2 public void testQueryUserById(){
       3     SqlSession session = MybatisUtils.getSession();
       4     UserMapper mapper = session.getMapper(UserMapper.class);
       5 
       6     User user = mapper.queryUserById(1);
       7     System.out.println(user);
       8 
       9     session.clearCache();//手动清除缓存
      10 
      11     User user2 = mapper.queryUserById(1);
      12     System.out.println(user2);
      13 
      14     System.out.println(user==user2);
      15 
      16     session.close();
      17 }

    (3)小结

    • 一级缓存默认开启,只在一次的SqlSession中有效( SqlSession session = MybatisUtils.getSession();  session.close(); 区间内有效)

    4.二级缓存

    • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存

    • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存;

    • 工作机制

      • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;

      • 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中

      • 新的会话查询信息,就可以从二级缓存中获取内容;

      • 不同的mapper查出的数据会放在自己对应的缓存(map)中;

    (1)步骤:

    • 开启全局缓存 【mybatis-config.xml】

      <setting name="cacheEnabled" value="true"/>
    • 使用:每个mapper.xml中配置使用二级缓存,这个配置非常简单;【xxxMapper.xml】

      <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/> 
      或 <cache />

    (2)结果:使用了二级缓存

    (3)问题:

    • 当我们直接使用 <cache /> 而不去配置参数时需要将实体类实现序列化接口不然可能会报错

    • 所有的实体类先实现序列化接口 implements Serializable 

     1 import lombok.AllArgsConstructor;
     2 import lombok.Data;
     3 import lombok.NoArgsConstructor;
     4 
     5 import java.io.Serializable;
     6 
     7 @Data
     8 @AllArgsConstructor
     9 @NoArgsConstructor
    10 public class User implements Serializable {
    11     private int id;
    12     private String name;
    13     private String pwd;
    14 
    15 }

    (4)小结:

    • 只要开启了二级缓存,我们在同一个Mapper中的查询,可以在二级缓存中拿到数据

    • 查出的数据都会被默认先放在一级缓存中

    • 只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中

    5.Mybatis缓存原理

    查询顺序:二级缓存-->一级缓存-->数据库

    6.自定义缓存Ehcache

    (1)介绍:

    • Ehcache是一种广泛使用的java分布式缓存,用于通用缓存;

    (2)使用:

    • 要在应用程序中使用Ehcache,需要引入依赖的jar包

      1 <!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
      2 <dependency>
      3     <groupId>org.mybatis.caches</groupId>
      4     <artifactId>mybatis-ehcache</artifactId>
      5     <version>1.1.0</version>
      6 </dependency>
    • 在mapper.xml中使用对应的缓存即可:

      1 <cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
    • 编写ehcache的配置文件ehcache.xml:

       1 <?xml version="1.0" encoding="UTF-8"?>
       2 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       3          xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
       4          updateCheck="false">
       5     <!--
       6        diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
       7        user.home – 用户主目录
       8        user.dir  – 用户当前工作目录
       9        java.io.tmpdir – 默认临时文件路径
      10      -->
      11     <diskStore path="./tmpdir/Tmp_EhCache"/>
      12     
      13     <defaultCache
      14             eternal="false"
      15             maxElementsInMemory="10000"
      16             overflowToDisk="false"
      17             diskPersistent="false"
      18             timeToIdleSeconds="1800"
      19             timeToLiveSeconds="259200"
      20             memoryStoreEvictionPolicy="LRU"/>
      21  
      22     <cache
      23             name="cloud_user"
      24             eternal="false"
      25             maxElementsInMemory="5000"
      26             overflowToDisk="false"
      27             diskPersistent="false"
      28             timeToIdleSeconds="1800"
      29             timeToLiveSeconds="1800"
      30             memoryStoreEvictionPolicy="LRU"/>
      31     <!--
      32        defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
      33      -->
      34     <!--
      35       name:缓存名称。
      36       maxElementsInMemory:缓存最大数目
      37       maxElementsOnDisk:硬盘最大缓存个数。
      38       eternal:对象是否永久有效,一但设置了,timeout将不起作用。
      39       overflowToDisk:是否保存到磁盘,当系统当机时
      40       timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
      41       timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
      42       diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
      43       diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
      44       diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
      45       memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
      46       clearOnFlush:内存数量最大时是否清除。
      47       memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
      48       FIFO,first in first out,这个是大家最熟的,先进先出。
      49       LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
      50       LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
      51    -->
      52 
      53 </ehcache>

  • 相关阅读:
    Promis.then()
    原生JS简单封装JSONP跨域获取数据
    原生JavaScript手写Ajax
    VS Code保存代码自动按eslint格式fix
    html data-xx 及 data()注意事项
    C#委托和事件
    vue devServer proxy 代理无效的问题
    vue .sync的使用
    js中,0的判断
    使用idea启动node项目的问题
  • 原文地址:https://www.cnblogs.com/zhihaospace/p/12302037.html
Copyright © 2011-2022 走看看