springboot(十九)cache缓存

166 阅读2分钟

缓存要求

  • queryList 方法用于查询所有用户,并将结果缓存起来。

  • queryOne 方法用于查询单个用户,并将结果缓存起来。

  • saveupdatedelete 方法在进行操作后,会清除所有缓存条目,以确保缓存数据的准确性。

数据库

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客户端

image.png

创建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默认为空

image.png

mysql数据

image.png

请求query-list用户列表

第一次请求

由于没有缓存,因此直接使用了mysql查询数据

image.png

同时也把数据缓存到redis中了

image.png

第二次以后的请求

此时还是之前的打印,但是返回了数据,证明没有使用mysql,而是读取了redis的缓存

image.png

修改,更新,删除

调用更新

image.png

更新后查询

此时原redis缓存会被删除,这次会使用mysql查询,并更新redis缓存

image.png

再次查询

发现又重新读取了redis的缓存

image.png