一.Mybatis缓存

什么是Mybatis缓存?

Mybatis为了提高查询的效率,内置了缓存机制。

缓存:把经常访问但是不经常修改的数据存储在缓存内容中,减少与数据库交互,从而达到提高效率的目的

Mybatis因为缓存的位置不一样又分为了2种缓存:一级缓存  和二级缓存 

一级缓存的数据存储在SqlSession对象里面 

二级缓存的数据存储在SqlSessionFactory对象里面
1 .一级缓存
image-20230222142703501

一级缓存特点:

一级缓存,默认存在,无法关闭

缓存的数据存储在SQLSession对象中(类似Map集合,键对应的sql语句,值就是语句对应的结果)

一级缓存如何保证数据一致性的:

当执行查询语句时,自动走缓存,缓存中如果有数据就返回,缓存没有就查询数据库,更新缓存

当执行非查询语句时(新增、修改、删除),就会自动删除缓存

接下来通过代码演示来验证缓存的存在

在验证之前先了解下Mybatis的日志如何配置,通过日志我们可以在控制台看到sql语句的打印信息

Mybatis内置的有日志记录,但是需要配置才会生效

日志配置步骤:

导入依赖jar

<!-- 日志处理 -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

在mybatis-config.xml中开启日志

    <settings>
<!--        开启日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

通过代码演示来验证缓存的存在

1)准备数据表

create table t_phone(
id int primary key auto_increment,
name varchar(20),
brand char(2),
model varchar(11),
price decimal(10,2),
ctime datetime
);

2).在pom.xml中导入所需要的依赖

    <dependencies>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.31</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.10</version>
        </dependency>
        <!--小辣椒-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <!-- 日志处理 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

3).创建Phone实体类

@Data
@NoArgsConstructor
public class Phone implements Serializable {
    private Integer id;
    private String name;
    private String brand;
    private String model;
    private Double price;
    private Date ctime;

    public Phone(String name, String brand, String model, Double price) {
        this.name = name;
        this.brand = brand;
        this.model = model;
        this.price = price;
    }
}

4).创建mapper接口(编写操作数据库的各种方法)

public interface PhoneDao {
    /**
     * 新增*/
    int add(Phone phone);
    /**
     * 查询*/
    List<Phone> selectAll();

}

5)创建mapper接口对应的映射文件(编写方法对应的sql语句)

<?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 namespace="com.feri.mybatis.dao.PhoneDao">
    <insert id="add" useGeneratedKeys="true" keyProperty="id">
        insert into t_phone(name,brand,model,price,ctime) values(#{name},#{brand},#{model},#{price},now())
    </insert>

    <select id="selectAll" resultType="com.feri.mybatis.entity.Phone">
        select * from t_phone
    </select>
</mapper>

6).在mybatis.xml中注册mapper映射文件

7)测试:

    @Test
    public void t1() throws IOException {
        //1.创建工厂对象
        SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(
                Resources.getResourceAsStream("mybatis-config.xml"));
        //2.获取 会话对象
        SqlSession session=factory.openSession(true);
        //3.获取接口的实现类对象
        PhoneDao dao=session.getMapper(PhoneDao.class);
        System.err.println("新增:"+dao.add(new Phone("苹果14Pro","苹果","14",8999.0)));
        System.err.println("查询:"+dao.selectAll());

    }

8)运行结果展示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dd6tdusz-1681711718719)(assets/1681691849554.png)]

验证验证缓存的一致性

1)测试:

public void t2() throws IOException {
    //1.创建工厂对象
    SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(
            Resources.getResourceAsStream("mybatis-config.xml"));
    //2.获取 会话对象
    SqlSession session=factory.openSession(true);
    //3.获取接口的实现类对象
    PhoneDao dao=session.getMapper(PhoneDao.class);
    System.err.println("查询1:"+dao.selectAll());
    System.err.println("新增:"+dao.add(new Phone("摩托罗拉Edgpro","摩托","edg",3999.0)));
    System.err.println("查询2:"+dao.selectAll());

}

2)运行结果展示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9HkURfUv-1681711718720)(assets/1681691994782.png)]

2.二级缓存
image-20230222144041654

二级缓存特点

二级缓存是把缓存的数据存储在SQLSessionFactory上面(对象内部)

二级缓存的数据,所有的session可以共用

二级缓存默认关闭,使用的需要配置

二级缓存实现步骤:

1.把要缓存的对象对应的类实现序列化接口

@Data
@NoArgsConstructor
public class Phone implements Serializable {
    private Integer id;
    private String name;
    private String brand;
    private String model;
    private Double price;
    private Date ctime;

    public Phone(String name, String brand, String model, Double price) {
        this.name = name;
        this.brand = brand;
        this.model = model;
        this.price = price;
    }
}

2.在mybatis-config中开启二级缓存

    <settings>
<!--        开启日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
<!--        开启二级缓存-->
        <setting name="cacheEnabled" value="true"/>
    </settings>

3.在需要使用二级缓存的映射文件中实现配置

<!--    二级缓存设置
        cache 二级缓存
        size属性:容量
        eviction:策略,容量满的时候,改按照什么规则删除缓存数据 常用:1.LRU(最近最少使用原则) 2.FIFO(先进先出) 3.Soft(软引用) 4.Weak(弱引用) -->
    <cache size="1024" eviction="LRU"></cache>

4.编写代码测试二级缓存

@Test
public void t4() throws IOException {
    //1.创建工厂对象
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(
            Resources.getResourceAsStream("mybatis-config.xml"));
    //2.获取 会话对象
    SqlSession session1 = factory.openSession(true);
    SqlSession session2 = factory.openSession(true);
    //3.验证二级缓存
    System.err.println("第一个会话:"+session1.getMapper(PhoneDao.class).selectAll());
    session1.close();
    System.err.println("第二个会话:"+session2.getMapper(PhoneDao.class).selectAll());
}

5.运行结果

image-20230411101833738

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐