• 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>

  • 相关阅读:
    PAT Advanced 1067 Sort with Swap(0, i) (25分)
    PAT Advanced 1048 Find Coins (25分)
    PAT Advanced 1060 Are They Equal (25分)
    PAT Advanced 1088 Rational Arithmetic (20分)
    PAT Advanced 1032 Sharing (25分)
    Linux的at命令
    Sublime Text3使用指南
    IntelliJ IDEA创建第一个Groovy工程
    Sublime Text3 安装ftp插件
    Sublime Text3配置Groovy运行环境
  • 原文地址:https://www.cnblogs.com/zhihaospace/p/12302037.html
Copyright © 2020-2023  润新知