我目前正在使用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而不删除之前?
谢谢
发布于 2018-06-22 10:55:55
要获取RedisKeyValueTemplate,您可以执行以下操作:
@Autowired
private RedisKeyValueTemplate redisKVTemplate;RedisKVTemplate.update(实体)
发布于 2018-01-19 18:34:46
您应该使用RedisKeyValueTemplate进行部分更新。
发布于 2020-05-11 15:13:22
好吧,考虑下面的文档link和spring data resulting (link)实际上对结果解决方案没有贡献。
考虑以下实体
@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;
}让我们假设:
entity = lastActivityCacheRepository.findByUser(userId);lastActivityCacheRepository.save(LastActivityCacheEntity.builder() .user(entity.getUser()) .lastLogin(entity.getLastLogin()) entity如果弹出大约100行怎么办?然后,在每次更新时,实体都会被获取并保存,效率很低,但仍然可以解决问题。
实际上,我们并不需要使用opsForHash + ObjectMapper +配置beans方法的复杂练习-它很难实现和维护(例如link)
所以我们将使用类似这样的东西:
@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
@Repository
public interface LastActivityCacheRepository extends CrudRepository<LastActivityCacheEntity, String>, LastActivityCacheRepositoryCustom {
Optional<LastActivityCacheEntity> findByUser(String user);
}LastActivityCacheRepositoryCustom.java
public interface LastActivityCacheRepositoryCustom {
void updateEntry(String userId, String key, long date);
}LastActivityCacheRepositoryCustomImpl.java
@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));
}
}最后是工作示例:
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注解。这将为您创建字段名常量,然后您可以像这样访问您的字段名:
...
if (update.getLastOperation() > 0) {
lastActivityCacheRepository.updateEntry(update.getUser(),
LastActivityCache.Fields.lastOperation, // <- instead of "lastOperation"
update.getLastOperation());
...这使得重构字段名变得更加防错。
https://stackoverflow.com/questions/48116466
复制相似问题