介绍Mybatis一级和二级缓存的基本概念,解释缓存的作用和优势,包括减少数据库访问、提高响应速度和减轻数据库负载。文章详细说明如何配置和使用二级缓存,包括启用方式和使用场景。
Mybatis缓存简介Mybatis一级缓存与二级缓存的概念
Mybatis缓存分为一级缓存和二级缓存。一级缓存是SqlSession级别的缓存,每个SqlSession都有自己的缓存,当SqlSession执行查询时,会优先检查此缓存,如果存在结果,则直接返回缓存中的数据。一级缓存默认开启,无需额外配置。
二级缓存是Mapper级别的缓存,可以在同一个Mapper中共享。二级缓存可以跨越多个SqlSession,这意味着在一个SqlSession中查询的数据,可以被另一个SqlSession使用,前提是这两个SqlSession共享同一个Mapper。但是,二级缓存默认是关闭的,需要手动开启。
缓存的作用和优势
缓存的主要作用是减少数据库访问次数,提高系统的响应速度和性能。在查询操作频繁且数据不频繁变化的场景下,启用缓存可以显著提升应用性能。
- 减少数据库访问:缓存可以避免每次查询都访问数据库,尤其是在数据不频繁变化的情况下。
- 提高响应速度:缓存减少了数据库的网络延迟,提高了系统的响应速度。
- 减轻数据库负载:缓存可以降低数据库的查询压力,减少数据库的负担。
二级缓存的启用方式
要启用二级缓存,需要满足以下条件:
- 在 Mybatis 的配置文件(如
mybatis-config.xml
或application.properties
)中,通过以下配置开启二级缓存:
<setting name="cacheEnabled" value="true"/>
或在 Spring Boot 的 application.properties
中:
mybatis.configuration.cache-enabled=true
- 在 Mapper 的 XML 文件中,为对应的 Mapper 启用缓存配置:
<mapper namespace="com.example.mapper.UserMapper">
<cache/>
</mapper>
缓存配置文件的编写
以下是启用缓存的完整配置示例:
- 在
mybatis-config.xml
中配置全局缓存启用:
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
- 在
UserMapper.xml
中启用二级缓存:
<mapper namespace="com.example.mapper.UserMapper">
<cache
eviction="LRU"
flushInterval="60000"
size="512"
readOnly="true"/>
<select id="findUserById" resultType="com.example.entity.User">
SELECT * FROM user WHERE id = #{id}
</select>
<select id="findAllUsers" resultType="com.example.entity.User">
SELECT * FROM user
</select>
</mapper>
- 配置
application.properties
启用缓存:
mybatis.configuration.cache-enabled=true
二级缓存的使用场景
何时开启二级缓存
以下是一些适合开启二级缓存的场景:
- 高并发读操作:如果一个数据库表的读操作非常频繁,可以考虑启用二级缓存以减少直接访问数据库的次数。
- 低频更新:当数据更新频率较低时,启用二级缓存可以有效地减少数据库压力。
- 查询结果不经常变化:如果查询返回的数据内容在较长时间内不会发生变化,启用二级缓存可以提高性能。
常见的使用场景分析
例如,在电子商务网站中,某些商品信息(如商品名称、价格、库存等)在一段时间内可能不会频繁更改。这类数据可以启用二级缓存来提高查询速度。
代码示例
package com.example.service;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User findUserById(int id) {
return userMapper.findUserById(id);
}
public List<User> findAllUsers() {
return userMapper.findAllUsers();
}
}
二级缓存的实现机制
缓存数据的存储方式
Mybatis的二级缓存默认使用LRU(Least Recently Used)缓存策略。LRU策略会根据时间来淘汰最近最少使用的数据,以此保证缓存中存储的是较新且常用的查询结果。
Mybatis支持多种缓存实现,包括内置的LRU缓存和自定义的缓存实现。自定义缓存实现需要实现 org.apache.ibatis.cache.Cache
接口。
缓存的数据更新策略
当缓存中的数据发生变化时,Mybatis会根据配置的缓存刷新策略来更新缓存。常见的缓存刷新策略包括:
- Scope.ALL:当数据库中的数据发生变化时,会自动刷新缓存。
- Scope.STATEMENT:当特定语句执行时,刷新缓存。
- Scope.SESSION:在会话结束时刷新缓存。
缓存刷新示例
在 UserMapper.xml
中可以配置刷新策略:
<mapper namespace="com.example.mapper.UserMapper">
<cache
eviction="LRU"
flushInterval="60000"
size="512"
readOnly="true"/>
<select id="findUserById" resultType="com.example.entity.User">
SELECT * FROM user WHERE id = #{id}
</select>
<select id="findAllUsers" resultType="com.example.entity.User">
SELECT * FROM user
</select>
</mapper>
eviction
:指定缓存淘汰策略,例如LRU
。flushInterval
:指定刷新缓存的间隔时间(单位:毫秒)。size
:指定缓存的最大条目数。readOnly
:设置缓存是否为只读模式。
二级缓存的注意事项
常见问题及解决方法
- 数据一致性问题:如果数据频繁变化,可能会导致缓存中的数据与数据库中的数据不一致。可以通过设置缓存刷新策略来缓解此问题。
- 缓存命中率低:如果缓存的命中率低,说明缓存设置可能不合理。可以调整缓存大小或刷新策略来优化缓存性能。
- 缓存击穿:当缓存中某个热点数据失效时,会导致大量的请求直接访问数据库,造成数据库压力过大。可以通过设置适当的缓存过期时间来缓解此问题。
性能优化建议
- 合理设置缓存大小和刷新策略:根据实际场景合理设置缓存大小和刷新策略,以提高缓存的命中率。
- 使用并发工具:使用并发工具(如
ConcurrentHashMap
)来提高缓存的读写性能。 - 缓存预热:在应用启动时预先加载一些常用的数据到缓存中,减少初始加载时间。
缓存刷新示例
在 UserService.java
中可以手动刷新缓存:
package com.example.service;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.apache.ibatis.cache.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User findUserById(int id) {
return userMapper.findUserById(id);
}
public List<User> findAllUsers() {
return userMapper.findAllUsers();
}
public void refreshUserCache() {
Cache cache = userMapper.getCache();
cache.clear();
}
}
通过调用 cache.clear()
方法可以清除缓存中的所有数据,强制重新从数据库中加载数据。
二级缓存的代码示例
以下是一个完整的示例,展示了如何在 Mybatis 中启用二级缓存,并通过代码示例来展示二级缓存的使用。
项目结构
src
└── main
├── java
│ └── com
│ └── example
│ ├── mapper
│ │ └── UserMapper.java
│ ├── service
│ │ └── UserService.java
│ └── entity
│ └── User.java
├── resources
│ ├── mybatis-config.xml
│ └── mapper
│ └── UserMapper.xml
UserMapper.java
package com.example.mapper;
import com.example.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
User findUserById(int id);
@Select("SELECT * FROM user")
List<User> findAllUsers();
}
User.java
package com.example.entity;
public class User {
private int id;
private String name;
private String email;
private int age;
// Getters and Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
UserMapper.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.mapper.UserMapper">
<cache
eviction="LRU"
flushInterval="60000"
size="512"
readOnly="true"/>
<select id="findUserById" resultType="com.example.entity.User">
SELECT * FROM user WHERE id = #{id}
</select>
<select id="findAllUsers" resultType="com.example.entity.User">
SELECT * FROM user
</select>
</mapper>
UserService.java
package com.example.service;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User findUserById(int id) {
return userMapper.findUserById(id);
}
public List<User> findAllUsers() {
return userMapper.findAllUsers();
}
public void refreshUserCache() {
Cache cache = userMapper.getCache();
cache.clear();
}
}
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
application.properties
mybatis.configuration.cache-enabled=true
实际项目中的应用案例
假设有一个电子商务网站,需要频繁查询用户的信息(如用户名、邮箱、年龄等)。由于这些信息在一段较长时间内不会频繁变动,因此可以启用二级缓存来提高查询速度。
代码示例
package com.example.service;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
/**
* 根据用户ID查询用户信息
* @param id 用户ID
* @return 用户信息
*/
public User findUserById(int id) {
return userMapper.findUserById(id);
}
/**
* 查询所有用户信息
* @return 用户列表
*/
public List<User> findAllUsers() {
return userMapper.findAllUsers();
}
}
使用缓存的查询方法
public User findUserById(int id) {
return userMapper.findUserById(id);
}
该方法会在首次查询时将查询结果存储到缓存中。后续的相同查询将直接从缓存中获取数据,而不会触发数据库查询。
缓存刷新
如果需要刷新缓存,可以通过以下方式手动刷新缓存:
package com.example.service;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.apache.ibatis.cache.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public void refreshUserCache() {
Cache cache = userMapper.getCache();
cache.clear();
}
}
通过调用 cache.clear()
方法可以清除缓存中的所有数据,强制重新从数据库中加载数据。
以上代码展示了如何在实际项目中启用和使用 Mybatis 的二级缓存,以提高系统的查询性能。
共同学习,写下你的评论
评论加载中...
作者其他优质文章