菜单

利用SpringDataRedis操作Redis数据,比RedisTemplate更方便

duckflew
发布于 2024-01-24 / 51 阅读
0
0

利用SpringDataRedis操作Redis数据,比RedisTemplate更方便

一般操作Redis,常用的做法是在SpringBoot中注入一个RedisTemplate,利用各种OpsForXXX来使用,利用Json序列化字符串到Redis当中

问题

用RedisTemplate的问题有 无法避免大Key的问题,以及需要自行组织key的命名规则

SpringDataRedis依赖

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
 </dependency>

 <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
 </dependency>

实体类配置

只需要在实体类上加一个RedisHash注解,指定存储的key前缀,然后在定义为id的字段上加上@Id即可 这里的@Id注解和Jpa的@Id作用差不多 但是不是同一个类

  • 这里的@Id注解是spingframework.data.annotation包下的
  • 而Jpa中的@Id注解karta.persist包下的

所以需要存储到Redis的实体类例子如下:

@Data
@AllArgsConstructor
@NoArgsConstructor
@RedisHash(RedisKeyPrefix.UNIT_CONNECT_STATUS)
@Builder
@FieldNameConstants
public class UnitConnectStatus implements Serializable {
    @Id
    private Integer unitId;

    private Integer unitType;

    private Boolean server2gateway;

    private Boolean gateway2unit;
}

创建Repo接口操作Redis数据

public interface ConnectRepo extends CrudRepository<UnitConnectStatus,Integer> {
    void updateServer2GatewayByUnitId(Boolean data,Integer unitId);
    void updateGateway2UnitByUnitId(Boolean data,Integer unitId);
}

只需要继承了CrudRepository 就可以像Jpa一样操作Redis的数据,在Redis中 CrudRepository用Hash格式来存储数据如下

Tips

使用这种方法操作Redis有几个点需要注意

  • repo.save操作不是原子的,如果频繁调用save方法的同时进行查询,有很大的概率会查询到空值,原因是save方法的逻辑是先删除再save,因此需要更新实体类的部分属性的时候尽量不用save操作,而是使用RedisKeyValueTemplate的update方法进行部分更新,部分更新的例子如下:

    新定义一个update的repo,对于需要更新不同类型的数据,可以重载方法

    @Component
    public class EscStatusUpdateRepo {
      private final RedisKeyValueTemplate redisKeyValueTemplate;
    
      @Autowired
      public EscStatusUpdateRepo(RedisKeyValueTemplate redisKeyValueTemplate) {
          this.redisKeyValueTemplate=redisKeyValueTemplate;
      }
      @Async
      public void updateEntry(String fieldName,Integer unitId, Boolean data) {
          Assert.notNull(unitId,"unitId is null");
          Assert.notNull(data,"fault is empty");
          redisKeyValueTemplate.update(new PartialUpdate<>(unitId,EscalatorStatus.class)
                  .set(fieldName,data)
          );
      }
    }
    
  • repo接口不支持像Jpa那样通过方法名解析特定的查询逻辑,例如在Jpa中我们可以通过定义一个接口的方法findByNameAndAge(String name,Integer age)来以name和age条件查询实体数据,这在Redis当中是不支持的


评论