首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用spring-data-redis更新redis中的实体

用spring-data-redis更新redis中的实体
EN

Stack Overflow用户
提问于 2018-01-05 23:20:25
回答 3查看 3.1K关注 0票数 4

我目前正在使用Redis (3.2.100)和Spring data redis (1.8.9)以及Jedis连接器。当我在现有实体上使用save()函数时,Redis会删除我的实体并重新创建该实体。

在我的例子中,我需要保留这个现有的实体,并且只更新实体的属性。(我有另一个线程同时读取相同的实体)

在Spring文档(https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/#redis.repositories.partial-updates)中,我发现了部分更新特性。不幸的是,文档中的示例使用了RedisTemplate的update()方法。但是这个方法并不存在。

那么你有没有使用过Spring-data-redis部分更新?

有没有其他方法可以更新实体redis而不删除之前?

谢谢

EN

回答 3

Stack Overflow用户

发布于 2018-06-22 10:55:55

要获取RedisKeyValueTemplate,您可以执行以下操作:

代码语言:javascript
复制
@Autowired
private RedisKeyValueTemplate redisKVTemplate;

RedisKVTemplate.update(实体)

票数 3
EN

Stack Overflow用户

发布于 2018-01-19 18:34:46

您应该使用RedisKeyValueTemplate进行部分更新。

票数 1
EN

Stack Overflow用户

发布于 2020-05-11 15:13:22

好吧,考虑下面的文档link和spring data resulting (link)实际上对结果解决方案没有贡献。

考虑以下实体

代码语言:javascript
复制
@RedisHash(value = "myservice/lastactivity")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LastActivityCacheEntity implements Serializable {
    @Id
    @Indexed
    @Size(max = 50)
    private String user;
    private long lastLogin;
    private long lastProfileChange;
    private long lastOperation;
}

让我们假设:

  1. 我们不想在每次更新时都做复杂的读写练习。

entity = lastActivityCacheRepository.findByUser(userId);lastActivityCacheRepository.save(LastActivityCacheEntity.builder() .user(entity.getUser()) .lastLogin(entity.getLastLogin()) entity如果弹出大约100行怎么办?然后,在每次更新时,实体都会被获取并保存,效率很低,但仍然可以解决问题。

实际上,我们并不需要使用opsForHash + ObjectMapper +配置beans方法的复杂练习-它很难实现和维护(例如link)

所以我们将使用类似这样的东西:

代码语言:javascript
复制
@Autowired
private final RedisKeyValueTemplate redisTemplate;

void partialUpdate(LastActivityCacheEntity update) {
  var partialUpdate = PartialUpdate
      .newPartialUpdate(update.getUser(), LastActivityCacheEntity.class);
  if (update.getLastLogin() > 0)
      partialUpdate.set("lastlastLogin", update.getLastLogin());
  if (update.getLastProfileChange() > 0)
      partialUpdate.set("lastProfileChange", update.getLastProfileChange());
  if (update.getLastOperation() > 0)
    partialUpdate.set("lastOperation", update.getLastOperation());
  redisTemplate.update(partialUpdate);
}

问题是-它对这种情况并不是真的有效。

也就是说,值正在更新,但您不能稍后通过存储库实体查找来查询新属性:某些lastActivityCacheRepository.findAll()将返回未更改的属性。

以下是解决方案:

LastActivityCacheRepository.java

代码语言:javascript
复制
@Repository
public interface LastActivityCacheRepository extends CrudRepository<LastActivityCacheEntity, String>, LastActivityCacheRepositoryCustom {
    Optional<LastActivityCacheEntity> findByUser(String user);
}

LastActivityCacheRepositoryCustom.java

代码语言:javascript
复制
public interface LastActivityCacheRepositoryCustom {
    void updateEntry(String userId, String key, long date);
}

LastActivityCacheRepositoryCustomImpl.java

代码语言:javascript
复制
@Repository
public class LastActivityCacheRepositoryCustomImpl implements LastActivityCacheRepositoryCustom {
    @Autowired
    private final RedisKeyValueTemplate redisKeyValueTemplate;

    @Override
    public void updateEntry(String userId, String key, long date) {
        redisKeyValueTemplate.update(new PartialUpdate<>(userId, LastActivityCacheEntity.class)
            .set(key, date));
    }
}

最后是工作示例:

代码语言:javascript
复制
void partialUpdate(LastActivityCacheEntity update) {
  if ((lastActivityCacheRepository.findByUser(update.getUser()).isEmpty())) {
      lastActivityCacheRepository.save(LastActivityCacheEntity.builder().user(update.getUser()).build());
  }
  if (update.getLastLogin() > 0) {
      lastActivityCacheRepository.updateEntry(update.getUser(),
          "lastlastLogin",
          update.getLastLogin());
  }
  if (update.getLastProfileChange() > 0) {
      lastActivityCacheRepository.updateEntry(update.getUser(),
          "lastProfileChange",
          update.getLastProfileChange());
  }
  if (update.getLastOperation() > 0) {
      lastActivityCacheRepository.updateEntry(update.getUser(),
          "lastOperation",
          update.getLastOperation());
}

所有功劳都归功于Chris Richardson和他的src

如果不想在updateEntry方法中以字符串形式输入字段名,可以在实体类@FieldNameConstants上使用use the lombok注解。这将为您创建字段名常量,然后您可以像这样访问您的字段名:

代码语言:javascript
复制
...
      if (update.getLastOperation() > 0) {
          lastActivityCacheRepository.updateEntry(update.getUser(),
              LastActivityCache.Fields.lastOperation, // <- instead of "lastOperation"
              update.getLastOperation());
...

这使得重构字段名变得更加防错。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48116466

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档