缓存要求
-
queryList方法用于查询所有用户,并将结果缓存起来。 -
queryOne方法用于查询单个用户,并将结果缓存起来。 -
save、update和delete方法在进行操作后,会清除所有缓存条目,以确保缓存数据的准确性。
数据库
CREATE TABLE `user` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(60) NULL DEFAULT NULL COMMENT '用户名' COLLATE 'utf8mb3_general_ci',
`age` INT(10) NULL DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`id`) USING BTREE
)
创建项目
redis
开启redis客户端
创建springboot项目
增加依赖
增加缓存相关依赖
redis: spring-boot-starter-data-redis
cache: spring-boot-starter-cache
完整依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>
</dependencies>
配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC
username: root
password: 123456
cache:
type: redis
data:
redis:
host: 127.0.0.1
port: 6379
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.cache.domain
server:
port: 8888
domain,mapper
使用插件自定义生成
domain
增加private static final long serialVersionUID = 1L;,Spring Cache 和 Redis,将对象缓存到 Redis 中时需要对象是可序列化的。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private Integer age;
}
serice
-
@EnableCaching: 开启缓存 -
@Cacheable:用于将方法的返回值缓存起来。queryList方法缓存所有用户列表,queryOne方法缓存单个用户的信息。 -
@CacheEvict:用于在增、删、改操作后清除缓存。这里我们使用了allEntries = true参数,表示清除userCache中的所有条目,因为增、删、改操作会影响缓存的准确性,需要重新查询数据并更新缓存。
@Service
@EnableCaching
public class UserService {
@Resource
private UserMapper userMapper;
@Cacheable(value = "userCache", key = "'userList'")
public Object queryList() {
UserExample userExample = new UserExample();
List<User> list = userMapper.selectByExample(userExample);
Map<String, Object> map = new HashMap<>();
System.out.println("queryList");
map.put("list",list);
return map;
}
@Cacheable(value = "userCache", key = "#id")
public Object queryOne(Integer id) {
System.out.println("queryOne");
return userMapper.selectByPrimaryKey(id);
}
@CacheEvict(value = "userCache", allEntries = true)
public void update(User user) {
userMapper.updateByPrimaryKeySelective(user);
}
@CacheEvict(value = "userCache", allEntries = true)
public void save(User user){
userMapper.insert(user);
}
@CacheEvict(value = "userCache", allEntries = true)
public void delete(Integer id) {
userMapper.deleteByPrimaryKey(id);
}
}
controller
@RestController
@RequestMapping("user")
public class UserController {
@Resource
private UserService userService;
@GetMapping("/query-list")
public Object queryList() {
return userService.queryList();
}
@GetMapping("/query-one")
public Object queryOne(@RequestParam Integer id){
return userService.queryOne(id);
}
@PutMapping("")
public String update(@RequestBody User user) {
userService.update(user);
return "ok";
}
@PostMapping("")
public String save(@RequestBody User user) {
userService.save(user);
return "ok";
}
@DeleteMapping("{id}")
public String delete(@PathVariable Integer id) {
userService.delete(id);
return "ok";
}
}
测试
初始
redis默认为空
mysql数据
请求query-list用户列表
第一次请求
由于没有缓存,因此直接使用了mysql查询数据
同时也把数据缓存到redis中了
第二次以后的请求
此时还是之前的打印,但是返回了数据,证明没有使用mysql,而是读取了redis的缓存
修改,更新,删除
调用更新
更新后查询
此时原redis缓存会被删除,这次会使用mysql查询,并更新redis缓存
再次查询
发现又重新读取了redis的缓存