Mybatis 二级缓存简单示例

简介: 本文通过一个简单示例演示MyBatis二级缓存的使用。主要内容包括:引入Maven依赖、配置SpringBoot文件、创建数据库与初始化SQL、编写实体类与Mapper,以及测试缓存功能。示例中展示了如何通过MyBatis的`<cache>`标签启用二级缓存,并验证了第二次查询直接从缓存中获取数据的过程。总结指出,SpringBoot MyBatis默认开启二级缓存,更多高级用法可进一步探索。

简介

简单接收Mybatis中二级缓存的使用示例

概览

主要部分如下:

  • 引入Maven依赖
  • SpringBoot配置文件配置、建库与初始化SQL语句
  • 实体类与Mapper编写
  • 测试

Maven依赖

完整依赖大致如下:

xml

体验AI代码助手

代码解读

复制代码

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    ......
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    ......
</project>

SpringBoot配置文件配置、建库与初始化SQL语句

配置文件如下:

yaml

体验AI代码助手

代码解读

复制代码

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  sql:
    init:
      schema-locations: classpath:mybatis/schema-mysql.sql
      data-locations: classpath:mybatis/data-mysql.sql

mybatis:
  configuration:
    cache-enabled: true
  mapper-locations: classpath:mybatis/mapper/*.xml

logging.level.com.example.cache.mapper: debug

建库DDL:

mysql

体验AI代码助手

代码解读

复制代码

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
    id BIGINT(20) NOT NULL COMMENT '主键ID',
    name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
);

数据初始化DDL:

mysql

体验AI代码助手

代码解读

复制代码

DELETE FROM `user`;

INSERT INTO `user` (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

实体类与Mapper编写

User实体类:

java

体验AI代码助手

代码解读

复制代码

import lombok.Data;

import java.io.Serializable;

@Data
public class User implements Serializable {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

UserMapper.java

java

体验AI代码助手

代码解读

复制代码

import com.example.cache.entity.User;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface UserMapper {

    List<User> select();
}

UserMapper.xml

xml

体验AI代码助手

代码解读

复制代码

<?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.example.cache.mapper.UserMapper"><cache/>
    <select id="select" resultType="com.example.cache.entity.User">
        select * from `user`;
    </select>
</mapper>

测试

测试代码如下:

java

体验AI代码助手

代码解读

复制代码

import com.example.cache.entity.User;
import com.example.cache.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
public class UserTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelectOneCache() {
        List<User> users = userMapper.select();
        Assertions.assertEquals(5, users.size());
        users.forEach(System.out::println);

        users = userMapper.select();
        Assertions.assertEquals(5, users.size());
        users.forEach(System.out::println);
    }
}

输出如下:

shell

体验AI代码助手

代码解读

复制代码

2021-06-08 22:38:48.925 DEBUG 7296 --- [           main] c.e.cache.mapper.UserMapper.select       : ==>  Preparing: select * from `user`;
2021-06-08 22:38:48.950 DEBUG 7296 --- [           main] c.e.cache.mapper.UserMapper.select       : ==> Parameters: 
2021-06-08 22:38:48.979 DEBUG 7296 --- [           main] c.e.cache.mapper.UserMapper.select       : <==      Total: 5
User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)
2021-06-08 22:38:48.995  WARN 7296 --- [           main] o.apache.ibatis.io.SerialFilterChecker   : As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66
2021-06-08 22:38:48.997 DEBUG 7296 --- [           main] com.example.cache.mapper.UserMapper      : Cache Hit Ratio [com.example.cache.mapper.UserMapper]: 0.5
User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)

可以看到第二次查询没有走SQL查询,直接从Cache中取得了结果

总结

一篇简单的Mybatis二级缓存的示例

从中可以看到,SpringBoot Mybatis是默认开启二级缓存的,其他更多的使用,如缓存失效等,后面再探索


转载来源:https://juejin.cn/post/6971435661819641863

相关文章
|
1月前
|
人工智能 Java Scala
Springboot捕获feign抛出的异常
本文探讨了在使用Springboot与Feign客户端时,如何有效捕获接口异常的问题。由于全局异常无法直接捕获Feign抛出的异常,文章提供了具体解决方案:通过定义自定义异常类`BusinessException`,结合`ErrorDecoder`对Feign请求异常进行处理,或在全局异常捕获中添加特定处理器。示例代码详细展示了配置与实现步骤,帮助开发者更好地应对Feign客户端的异常处理需求。
|
6月前
|
安全 Java API
Spring Boot 3.x 在 2.x基础上有什么重大的改进?
Spring Boot 3.x于2022年11月发布,带来了诸多重大更新。主要改进包括:最低要求Java 17,整合Jakarta EE 9,优化实例化和配置支持,基于Spring Framework 6.x,引入AOT编译,增强GraalVM原生映像支持,改进日志管理和集成测试,提供更详细的Actuator监控功能,以及对Spring Cloud的兼容性更新。这些变化为现代云原生应用开发提供了更强支持。
405 36
|
8月前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
227 2
|
5月前
|
消息中间件 Java API
深入简出的带你精通java线程
线程与进程是操作系统中的两个重要概念。进程是资源分配的最小单位,负责加载指令、管理内存和IO;线程是CPU调度的最小单位,也被称为轻量级进程。
136 36
深入简出的带你精通java线程
|
3月前
|
Java Spring 容器
两种Spring Boot 项目启动自动执行方法的实现方式
在Spring Boot项目启动后执行特定代码的实际应用场景中,可通过实现`ApplicationRunner`或`CommandLineRunner`接口完成初始化操作,如系统常量或配置加载。两者均支持通过`@Order`注解控制执行顺序,值越小优先级越高。区别在于参数接收方式:`CommandLineRunner`使用字符串数组,而`ApplicationRunner`采用`ApplicationArguments`对象。注意,`@Order`仅影响Bean执行顺序,不影响加载顺序。
146 2
|
4月前
|
存储 缓存 安全
Java 字符串详解
本文介绍了 Java 中的三种字符串类型:String、StringBuffer 和 StringBuilder,详细讲解了它们的区别与使用场景。String 是不可变的字符串常量,线程安全但操作效率较低;StringBuffer 是可变的字符串缓冲区,线程安全但性能稍逊;StringBuilder 同样是可变的字符串缓冲区,但非线程安全,性能更高。文章还列举了三者的常用方法,并总结了它们在不同环境下的适用情况及执行速度对比。
137 17
|
5月前
|
存储 缓存 安全
Java HashMap详解及实现原理
Java HashMap是Java集合框架中常用的Map接口实现,基于哈希表结构,允许null键和值,提供高效的存取操作。它通过哈希函数将键映射到数组索引,并使用链表或红黑树解决哈希冲突。HashMap非线程安全,多线程环境下需注意并发问题,常用解决方案包括ConcurrentHashMap和Collections.synchronizedMap()。此外,合理设置初始化容量和加载因子、重写hashCode()和equals()方法有助于提高性能和避免哈希冲突。
241 17
Java HashMap详解及实现原理
|
11月前
|
JSON 前端开发 Java
如何封装接口返回结构?
本文详细探讨了API接口返回结构统一化的必要性及其带来的优势,如降低开发的心智负担、减少前端开发难度和提高代码可维护性等。同时也分析了其潜在的缺点,例如灵活性降低和开发成本增加等问题。文章进一步讨论了在Spring Boot中实现统一接口返回结构的具体方法和技术细节,包括如何处理HTTP状态码、返回单个字符串的情况以及如何封装无返回值的接口等。此外,还介绍了如何利用Spring Boot的`ResponseBodyAdvice`和`@RestControllerAdvice`等特性来自动包装控制器方法的返回值及异常处理,以达到更加一致和标准化的接口响应结构。
177 3
如何封装接口返回结构?
|
4月前
|
人工智能 JSON Java
列表结构与树结构转换分析与工具类封装(java版)
本文介绍了将线性列表转换为树形结构的实现方法及工具类封装。核心思路是先获取所有根节点,将其余节点作为子节点,通过递归构建每个根节点的子节点。关键在于节点需包含 `id`、`parentId` 和 `children` 三个属性。文中提供了两种封装方式:一是基于基类 `BaseTree` 的通用工具类,二是使用函数式接口实现更灵活的方式。推荐使用后者,因其避免了继承限制,更具扩展性。代码示例中使用了 Jackson 库进行 JSON 格式化输出,便于结果展示。最后总结指出,理解原理是进一步优化和封装的基础。
|
5月前
|
IDE Java 应用服务中间件
spring boot 启动流程
Spring Boot 启动流程简介: 在使用 Spring Boot 之前,启动 Java Web 应用需要配置 Web 容器(如 Tomcat),并将应用打包放入容器目录。而使用 Spring Boot,只需运行 main() 方法即可启动 Web 应用。Spring Boot 的核心启动方法是 SpringApplication.run(),它负责初始化和启动应用上下文。 主要步骤包括: 1. **应用启动计时**:使用 StopWatch 记录启动时间。 2. **打印 Banner**:显示 Spring Boot 的 LOGO。 3. **创建上下文实例**:通过反射创建
315 5