MyBatis 是一种流行的持久层框架,支持 SQL 的自定义执行、映射以及复杂查询。MyBatis 提供了两级缓存机制:一级缓存和二级缓存。一级缓存是基于 SqlSession
的缓存,而二级缓存则是跨 SqlSession
的缓存。使用缓存可以大大提高查询的性能,因为重复的查询不会每次都访问数据库,而是从缓存中获取结果。
场景案例
假设我们有一个电商系统,其中有一个用户表 users
,每次请求需要获取用户的信息。为了减少数据库访问,我们可以通过 MyBatis 的缓存机制来缓存用户数据,特别是那些频繁访问且变化不频繁的用户信息。
步骤 1:项目环境搭建
在 Spring Boot 中集成 MyBatis 和缓存,可以通过配置 mybatis-spring-boot-starter
来实现。
1.1 添加依赖
在 pom.xml
中添加 MyBatis 和 Spring Boot 的依赖:
xml
代码解读
复制代码
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis Spring Boot Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok (Optional for simplicity) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
1.2 配置数据库连接
在 application.yml
中配置 MySQL 数据库连接信息:
yaml
代码解读
复制代码
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis_cache_db
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.mybatiscache.model
configuration:
cache-enabled: true # 启用 MyBatis 二级缓存
1.3 创建数据库表
sql
代码解读
复制代码
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
email VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
步骤 2:实现缓存机制
2.1 创建实体类
User.java
:
java
代码解读
复制代码
package com.example.mybatiscache.model;
import lombok.Data;
import java.sql.Timestamp;
@Data
public class User {
private Long id;
private String name;
private String email;
private Timestamp createdAt;
}
2.2 编写 Mapper 接口
UserMapper.java
:
java
代码解读
复制代码
package com.example.mybatiscache.mapper;
import com.example.mybatiscache.model.User;
import org.apache.ibatis.annotations.*;
@Mapper
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User getUserById(Long id);
@Insert("INSERT INTO users(name, email) VALUES(#{name}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insertUser(User user);
}
2.3 编写 Mapper XML 文件
mapper/UserMapper.xml
:
xml
代码解读
复制代码
<?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.mybatiscache.mapper.UserMapper">
<!-- 开启二级缓存 -->
<cache/>
<select id="getUserById" parameterType="long" resultType="com.example.mybatiscache.model.User">
SELECT * FROM users WHERE id = #{id}
</select>
</mapper>
2.4 编写 Service 层
UserService.java
:
java
代码解读
复制代码
package com.example.mybatiscache.service;
import com.example.mybatiscache.mapper.UserMapper;
import com.example.mybatiscache.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User getUserById(Long id) {
return userMapper.getUserById(id);
}
@Transactional
public void addUser(User user) {
userMapper.insertUser(user);
}
}
步骤 3:测试缓存机制
3.1 编写控制器
UserController.java
:
java
代码解读
复制代码
package com.example.mybatiscache.controller;
import com.example.mybatiscache.model.User;
import com.example.mybatiscache.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getUserById(id);
}
@PostMapping("/")
public User createUser(@RequestBody User user) {
userService.addUser(user);
return user;
}
}
3.2 验证缓存效果
- 启动 Spring Boot 项目。
- 通过 Postman 或 Curl 插入新用户:
bash
代码解读
复制代码
curl -X POST http://localhost:8080/users/ \
-H "Content-Type: application/json" \
-d '{"name": "John", "email": "john@example.com"}'
- 获取用户信息:
bash
代码解读
复制代码
curl http://localhost:8080/users/1
- 多次执行相同的 GET 请求,观察控制台日志,可以看到相同的 SQL 语句只执行一次,这说明第二次获取时是从缓存中获取数据的。
步骤 4:MyBatis 缓存机制原理
- 一级缓存:MyBatis 的一级缓存是
SqlSession
级别的缓存。在同一个SqlSession
中,相同的查询结果会缓存起来,再次执行时,直接从缓存中获取,避免重复访问数据库。一级缓存是默认开启的,且作用范围是SqlSession
。 - 二级缓存:MyBatis 提供了跨
SqlSession
的二级缓存,作用范围是Mapper
。二级缓存需要在 MyBatis 的 XML 文件中配置<cache/>
来开启。MyBatis 会将查询结果缓存到内存中,之后的相同查询可以直接从缓存中返回结果,而不需要再次访问数据库。
缓存更新机制
- 当执行
INSERT
、UPDATE
或DELETE
操作时,MyBatis 会自动清除相关的缓存,确保缓存数据和数据库数据保持一致。 - 在上面的案例中,我们只要调用了
createUser
方法插入新用户,MyBatis 就会清除与用户相关的缓存数据,保证下次查询时获取到的是最新的数据。
总结
通过以上步骤,我们在一个简单的 Spring Boot 项目中集成了 MyBatis 的一级和二级缓存机制,并通过一个实际的场景案例展示了缓存的使用及其原理。这样,我们可以提高系统的查询性能,减少对数据库的频繁访问。