一、为什么要缓存
随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,数据库的访问越少越好,此时使用缓存往往是解决这一问题非常好的手段之一。
在开发中,如果相同的查询条件去频繁查询数据库, 会给数据库带来很大的压力。因此,我们需要对查询出来的数据进行缓存,这样客户端只需要从数据库查询一次数据,然后会放入缓存中,以后再次查询时可以从缓存中读取,这能大大减少访问时间。
本文来介绍 SpringBoot 来简单整合缓存,使用 SpringBoot + MyBatis + MySQL来进行数据库操作。
二、项目依赖与配置
1、pom.xml 引入依赖
为测试方便,除了 cache 依赖之外,还引入了 mysql、jdbc、mybatis 的依赖。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
|
2、application.properties配置文件
项目连接数据库的基本配置。
1 2 3 4 5 6
| spring.datasource.username=root spring.datasource.password=12345678 spring.datasource.url=jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis.configuration.map-underscore-to-camel-case=true
|
三、数据库与实体类创建
1、数据库创建
简单起见,这里创建一个 student
表,里面只有 3 个字段:student_id
,student_name
,student_age
。
在表中加几条数据:
2、对应的实体类
1 2 3 4 5 6 7 8 9 10 11
| import lombok.Data;
@Data public class Student {
private Integer studentId; private String studentName; private Integer studentAge; }
|
三、Mapper层和Service层编写
1、Mapper层对数据CRUD操作编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import org.apache.ibatis.annotations.*;
@Mapper public interface StudentMapper {
@Select("select * from student where student_id = #{id}") Student getStudentById(Integer id);
@Delete("delete from student where student_id = #{id}") int deleteStudentById(Integer id);
@Options(useGeneratedKeys = true, keyProperty = "student_id") @Insert("insert into student(student_name) values(#{studentName})") int insertStudent(Student student);
@Update("update student set student_name = #{studentName} where student_id = #{studentId}") int updateStudent(Student student); }
|
2、缓存注解
所谓的缓存,就是将方法的运行结果进行缓存;以后再要相同的数据,直接从缓存中获取,不用调用方法。
SpringBoot 的自动配置类 CacheAutoConfiguration
给容器中注册了一个 CacheManager:ConcurrentMapCacheManager
,可以获取和创建 ConcurrentMapCache
类型的缓存组件;他的作用将数据保存在 ConcurrentMap
中;CacheManager 管理多个 Cache 组件的,对缓存的真正CRUD操作在Cache组件中。
注解 |
作用 |
@Cacheable |
主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 |
@CacheEvict |
清空缓存 |
@CachePut |
保证方法被调用,又希望结果被缓存。 |
@EnableCaching |
开启基于注解的缓存 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service;
@Service public class StudentServies {
@Autowired private StudentMapper studentMapper;
@Cacheable(value = "stu", key = "#id") public Student getStu(Integer id) { Student student = studentMapper.getStudentById(id); System.out.print("查询id = " + id + ": "); System.out.println(student); return student; }
@CachePut(value = "stu", key = "#student.studentId") public Student updateStu(Student student) { int s1 = studentMapper.updateStudent(student); System.out.println("更新"); System.out.println(s1); return student; } }
|
注意:
@Cacheable
和 @CachePut
标注的方法的返回值必须相同。
- 不同
value
中的数据是不同的,即使 key
是相同的。
@Cacheable
/@CachePut
/@CacheEvict
主要的参数:
注解 |
作用 |
value |
缓存的名称,在 Spring 配置文件中定义,必须指定至少一个 |
key |
缓存的 key,如果为空则按照方法的所有参数进行组合,如果指定则要按照 SpEL 表达式编写 |
condition |
缓存的条件,可以为空,使用 SpEL 编写,返回 true 或false,只有为 true 才进行缓存/清除缓存,在调用方法前后都能判断 |
allEntries |
是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存 |
beforeInvocation |
是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存, 缺省情况下,如果方法执行抛出异常,则不会清空缓存 |
unless |
用于否决缓存的,不像condition,该表达式只在方法执行之后判断,此时可以拿到返回值result进行判断。条件为true不会缓存,fasle才缓存 |
例如:
1 2 3 4 5 6 7 8
| @CachePut(value = "stu", key = "#student.studentId", condition = "#student.studentAge > 1", unless = "#result.personId < 0") public Student updateStu(Student student) { int s1 = studentMapper.updateStudent(student); System.out.println("更新"); System.out.println(s1); return student; }
|