目录
一、几个重要的概念
1、一些重要的注解
2、注解参数
3、SpEL表达式可以使用的一些源数据
二、具体实现
其中springboot整合mybatis以及利用docker安装redis可参照我的上一篇博客
1、首先打开redis(我使用的是docker)
2、全局配置文件application.yml
配置redis服务器的ip地址
3、开启基于注解的缓存
4、将方法的运行结果进行缓存
5、结果
第一次访问的时候查询数据库;第二次访问相同内容时就从缓存中查询
三、缓存工作原理
四、@Cacheable其他属性
1、cacheNames/value:指定缓存组件的名字;将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存
2、key:缓存数据使用key;可以用它来指定。默认是使用方法参数的值
3、keyGenerator:key的生成器,可以自己指定key的生成器的组件id;key/keyGenerator二选一使用
@Configuration
public class MyCacheConfig {
@Bean(name = "myKeyGenerator")
public KeyGenerator keyGenerator(){
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
return method.getName()+"["+Arrays.asList(params).toString() +"]";
}
};
}
}
使用:指定keyGenerator 的id
@Cacheable(cacheNames ={"emp"},keyGenerator = "myKeyGenerator")
4、cacheManager:制指定缓存管理器,或者CacheResolver指定获取解析器
5、condition:指定符合条件的情况下缓存,condition="#id>0"
6、unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断
7、sync:是否使用异步模式
五、@CachePut
既调用方法,又更新缓存数据。修改了数据库中的某个数据,同时更新缓存
方法运行之后给缓存中放数据!!!
@CachePut(cacheNames = "emp")
public Employee updateEmp(Employee employee){
System.out.println("updateEmp:"+employee);
employeeMapper.updateEmp(employee);
return employee;
}
注意:这种做法有一个问题,就是如果更新了1号员工的数据,那么再查询的时候仍然是从缓存中查询,查到的是更新前的数据。因为之前缓存用到的key是员工的id(默认ji为参数),这个方法用到的key是employee,所以说并没有更新。那应该怎么处理呢?
指定key=#{employee.id} 或#{result.id} 保持和上面缓存方法具有相同的key
即:
@CachePut(cacheNames = "emp",key = "#employee.id")
public Employee updateEmp(Employee employee){
System.out.println("updateEmp:"+employee);
employeeMapper.updateEmp(employee);
return employee;
}
六、@CacheEvict
缓存清除:
说明:
七、@Caching和@CacheConfig
@Caching:定义复杂的缓存规则
@Caching(
cacheable = {
@Cacheable(value = "emp",key = "#lastName")
},
put = {
@CachePut(value = "emp",key = "#result.id"),
@CachePut(value = "emp",key = "#result.email")
}
)
public Employee getEmpByLastName(String lastName){
return employeeMapper.getEmpByLastName(lastName);
}
@CacheConfig:抽取缓存的公共配置
---------------------------------------------------------------------------------------------------------------------------------------------------------
八、完整代码
1、配置文件
(1)pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</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>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
(2)application.yml
spring:
datasource:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot_cache?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC
redis:
host: 10.12.78.203
mybatis:
configuration:
map-underscore-to-camel-case: true #开启驼峰命名
logging:
level:
com.atguigu.springboot.cache.mapper: debug
debug: true
(3)全局入口文件
@EnableCaching//开启基于注解的缓存
@MapperScan(value = "com.atguigu.springboot.cache.mapper")
@SpringBootApplication
public class SpringbootCacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootCacheApplication.class, args);
}
}
2、mapper层
@Mapper
public interface EmployeeMapper {
@Select("select * from employee where id = #{id}")
public Employee getEmpById(Integer id);
@Delete("delete from employee where id = #{id}")
public int deleteEmpById(Integer id);
@Update("update employee set lastName = #{lastName},email=#{email} ,gender = #{gender},d_id=#{dId} where id = #{id}")
public int updateEmp(Employee employee);
@Insert("insert into employee(lastName,email,gender,d_id) values(#{lastName},#{email},#{gender},#{dId})")
public int insertEmp(Employee employee);
@Select("select * from employee where lastName = #{lastName} ")
Employee getEmpByLastName(String lastName);
}
3、Service层
@Service
public class EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Cacheable(cacheNames ={"emp"}/*,key = "#root.methodName+'['+#id+']'"*/)//将方法的运行结果进行缓存
//@Cacheable(cacheNames ={"emp"},keyGenerator = "myKeyGenerator")//将方法的运行结果进行缓存
public Employee getEmpById(Integer id){
System.out.println("查询"+id+"号员工");
Employee emp = employeeMapper.getEmpById(id);
return emp;
}
@CachePut(cacheNames = "emp",key = "#employee.id")
public Employee updateEmp(Employee employee){
System.out.println("updateEmp:"+employee);
employeeMapper.updateEmp(employee);
return employee;
}
@CacheEvict(cacheNames = "emp",key = "#id")//通过key指定要清除的数据,不指定的时候默认是参数
public void delEmp(Integer id){
System.out.println("delEmp:"+id);
// employeeMapper.deleteEmpById(id);
}
@Caching(
cacheable = {
@Cacheable(value = "emp",key = "#lastName")
},
put = {
@CachePut(value = "emp",key = "#result.id"),
@CachePut(value = "emp",key = "#result.email")
}
)
public Employee getEmpByLastName(String lastName){
return employeeMapper.getEmpByLastName(lastName);
}
}
4、Controller层
@RestController
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@GetMapping("/emp/{id}")
public Employee getEmpById(@PathVariable("id") Integer id){
return employeeService.getEmpById(id);
}
@GetMapping("/emp")
public Employee updateEmp(Employee employee){
return employeeService.updateEmp(employee);
}
@GetMapping("/delEmp/{id}")
public String delEmp(@PathVariable("id") Integer id){
employeeService.delEmp(id);
return "success";
}
@GetMapping("/emp/lastName/{lastName}")
public Employee getEmpByLastName(@PathVariable("lastName") String lastName){
return employeeService.getEmpByLastName(lastName);
}
}