二十六、二级缓存

狂神说Java:https://www.bilibili.com/video/BV1NE411Q7Nx

1、概念

https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#cache

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

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

工作机制:

  • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中。
  • 如果当前会话关闭了,这个会话对应的一级缓存就没了。但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中
  • 新的会话查询信息,就可以从二级缓存中获取。
  • 不同的mapper查出的数据会放在自己对应的缓存(map)中。

2、核心配置文件显示开启缓存

设置名描述有效值默认值
cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true | falsetrue
<settings>
    <!--显示开启全局缓存-->
    <setting name="cacheEnabled" value="true"/>
</settings>

3、在要使用二级缓存的mapper文件开启缓存

<!--在当前mapper使用二级缓存-->
<cache/>

自定义

<!--在当前mapper使用二级缓存-->
<cache eviction="FIFO"
       flushInterval="60000"
       size="512"
       readOnly="true"/>

4、测试

/**
 * 二级缓存测试
 */
@Test
public void test03(){

    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user = userMapper.getUserById8(1);
    System.out.println(user);
    sqlSession.close();

    /**
         * 一级缓存失效
         */

    SqlSession sqlSession2 = MybatisUtils.getSqlSession();
    UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
    User user2 = userMapper2.getUserById8(1);
    System.out.println(user2);

    System.out.println(user == user2);

    sqlSession2.close();

}

mapper未开启二级缓存

Opening JDBC Connection
Created connection 1233705144.
==>  Preparing: select * from user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 狂神, 123456
<==      Total: 1
User(id=1, name=狂神, pwd=123456)
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4988d8b8]
Returned connection 1233705144 to pool.
Opening JDBC Connection
Checked out connection 1233705144 from pool.
==>  Preparing: select * from user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 狂神, 123456
<==      Total: 1
User(id=1, name=狂神, pwd=123456)
false
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4988d8b8]
Returned connection 1233705144 to pool.

Process finished with exit code 0

可以发现,查询了2次数据库。

mapper文件开启二级缓存

<!--在当前mapper使用二级缓存-->
<cache eviction="FIFO"
       flushInterval="60000"
       size="512"
       readOnly="true"/>

结果

Cache Hit Ratio [com.kuang.dao.UserMapper]: 0.0
Opening JDBC Connection
Created connection 1911152052.
==>  Preparing: select * from user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 狂神, 123456
<==      Total: 1
User(id=1, name=狂神, pwd=123456)
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@71e9ddb4]
Returned connection 1911152052 to pool.
Cache Hit Ratio [com.kuang.dao.UserMapper]: 0.5
User(id=1, name=狂神, pwd=123456)
true

Process finished with exit code 0

从结果发现,只查了一次数据库。第二次查的是二级缓存。

5、实体类序列化的问题

mapper文件不配置二级缓存参数

<!--开启二级缓存-->
<cache/>

会报错:

org.apache.ibatis.cache.CacheException: Error serializing object.  Cause: java.io.NotSerializableException: com.kuang.pojo.User

序列化实体类

package com.kuang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * @Description TODO
 * @Author Administrator
 * @Date 2020/12/1 11:27
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private int id;
    private String name;
    private String pwd;
}

这样设置之后,测试结果正常。

Cache Hit Ratio [com.kuang.dao.UserMapper]: 0.0
Opening JDBC Connection
Created connection 1708169732.
==>  Preparing: select * from user where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 狂神, 123456
<==      Total: 1
User(id=1, name=狂神, pwd=123456)
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@65d09a04]
Returned connection 1708169732 to pool.
Cache Hit Ratio [com.kuang.dao.UserMapper]: 0.5
User(id=1, name=狂神, pwd=123456)
false
user的hashcode = 1506349811
user2的hashcode = 1506349811

Process finished with exit code 0

因为实体类实现了序列化接口。序列化是深拷贝,所以反序列化后的队象和原对象不是同一个对象,故hash值不同

6、总结

  • 只要开启了二级缓存,在同一个Mapper下就有效!
  • 所有的数据都会先放在一级缓存中。
  • 只有当会话提交或者关闭的时候,才会提交到二级缓存中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值