我们在上一篇的基础上继续学习。
一、@Caching注解
@Caching注解用于在方法或者类上,同时指定多个Cache相关的注解。
属性名 | 描述 |
cacheable | 用于指定@Cacheable注解 |
put | 用于指定@CachePut注解 |
evict | 用于指定@CacheEvict注解 |
示例代码如下:
import com.example.myspringboot.bean.Student;
import com.example.myspringboot.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import java.util.Optional;
/**
* @author qx
* @date 2023/06/20
* @desc 服务层
*/
@Service
public class StudentService {
@Autowired
private StudentRepository studentRepository;
@Cacheable(value = "student", key = "#id")
public Student getStudent(Long id) {
return studentRepository.findById(id).orElse(null);
}
@Caching(cacheable = {@Cacheable(value = "student", key = "#student.id")}, put = {@CachePut(value = "student", key = "#student.id")})
public Student saveStudent(Student student) {
studentRepository.save(student);
return student;
}
}
在saveStudent方法中,@Caching注解中使用了cacheable属性和put属性,该方法先是使用@Cacheable注解查询缓存缓存,然后再使用@CachePut注解把缓存存储到指定的key中。
控制层代码:
import com.example.myspringboot.bean.Student;
import com.example.myspringboot.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author qx
* @date 2023/06/19
* @desc
*/
@RestController
@RequestMapping("/student")
public class StudentController {
@Autowired
private StudentService studentService;
@GetMapping("/{id}")
public Student getStudent(@PathVariable Long id) {
return studentService.getStudent(id);
}
@GetMapping("/save")
public Student updateStudent(Student student) {
return studentService.saveStudent(student);
}
}
测试:
Hibernate: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from t_student student0_ where student0_.id=?
Hibernate: update t_student set age=?, name=? where id=?
我们调用新增的方法,先是清除了缓存然后再添加到缓存。
我们再次请求查询数据接口发现控制台没有执行sql语句
二、@CacheConfig注解
@CacheConfig注解可以把一些缓存配置提取到类级别的一个地方,这样我们就不必在每个方法都设置相关的配置。
我们之前设置缓存可以使用如下代码:
import com.example.myspringboot.bean.Student;
import com.example.myspringboot.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
/**
* @author qx
* @date 2023/06/19
* @desc 服务层
*/
@Service
public class StudentService {
@Autowired
private StudentRepository studentRepository;
@Cacheable(value = "student", key = "#id")
public Student getStudent(Long id) {
return studentRepository.findById(id).orElse(null);
}
@CachePut(value = "student", key = "#student.id")
public Student saveStudent(Student student) {
studentRepository.save(student);
return student;
}
/**
* 清除缓存
*/
@CacheEvict(value = "student", key = "#id")
public void deleteCache(Long id) {
System.out.println("清除缓存");
}
}
然后我们使用@CacheConfig配置公共的缓存变量。
import com.example.myspringboot.bean.Student;
import com.example.myspringboot.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
/**
* @author qx
* @date 2023/06/19
* @desc 服务层
*/
@Service
@CacheConfig(cacheNames = {"student"})
public class StudentService {
@Autowired
private StudentRepository studentRepository;
@Cacheable(key = "#id")
public Student getStudent(Long id) {
return studentRepository.findById(id).orElse(null);
}
@CachePut(key = "#student.id")
public Student saveStudent(Student student) {
studentRepository.save(student);
return student;
}
/**
* 清除缓存
*/
@CacheEvict(key = "#id")
public void deleteCache(Long id) {
System.out.println("清除缓存");
}
}
测试后发现效果是一样的。
三、condition&unless属性
condition:指定缓存的条件,满足什么条件才缓存。
unless: 否定缓存,当满足unless条件时,方法的结果不就行缓存。
// ID大于0才会进行缓存
@Cacheable(key = "#id", condition = "#id>0")
public Student getStudent(Long id) {
return studentRepository.findById(id).orElse(null);
}
四、allEntries&beforeInvocation属性
这两个属性都可以清除全部缓存数据,不过allEntries是方法调用后清理,beforeInvocation是方法调用前清理。
import com.example.myspringboot.bean.Student;
import com.example.myspringboot.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
/**
* @author qx
* @date 2023/06/19
* @desc 服务层
*/
@Service
@CacheConfig(cacheNames = {"student"})
public class StudentService {
@Autowired
private StudentRepository studentRepository;
@Cacheable(key = "#id", condition = "#id>0")
public Student getStudent(Long id) {
return studentRepository.findById(id).orElse(null);
}
@CachePut(key = "#student.id")
public Student saveStudent(Student student) {
studentRepository.save(student);
return student;
}
/**
* 清除所有缓存
*/
@CacheEvict(allEntries = true)
public void deleteCache() {
System.out.println("清除缓存");
}
}
清除所有缓存并查询两个数据并缓存
清除缓存
Hibernate: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from t_student student0_ where student0_.id=?
Hibernate: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from t_student student0_ where student0_.id=?
重新重新数据发现重新执行了sql语句
清除缓存
Hibernate: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from t_student student0_ where student0_.id=?
Hibernate: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from t_student student0_ where student0_.id=?
清除缓存
Hibernate: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from t_student student0_ where student0_.id=?
五、集成Redis实现缓存
1.添加依赖
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.配置Redis做为缓存管理器
#设置缓存类型,这里使用Redis作为缓存服务器
spring.cache.type=redis