Hazelcast replace(id, old, new) 不调用我的 MapStore
Hazelcast replace(id, old, new) not calling my MapStore
我正在尝试按照 here 所述在 Hazelcast 中实施乐观并发检查。我已经将我的 MapConfigs 设置为使用 InMemoryFormat.OBJECT,并且我已经使用 equals() 和 hashCode() 向我的 BaseEntity 添加了一个版本字段,定义如下:
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
BaseEntity that = (BaseEntity) o;
return getId().equals(that.getId()) && getVersion() == that.getVersion();
}
@Override
public int hashCode() {
return (int) (getId().hashCode() + version);
}
在我的 BaseService 中,我将 map.replace(id, entity) 替换为 3 arg 版本,如下所示:
instance.incrementVersion();
if (getTransactionalMap().replace(instance.getId(), existing, instance)) {
// do some stuff here
} else {
throw new OptimisticConcurrencyServiceException(
"Could not replace existing " + existing.getEntityId() + " with version " + existing.getVersion());
}
我遇到的问题是更新时未调用我的 MapStore。在一次交易中,我创建了一个对象并通过我的 BaseService.create() 方法将其存储到地图(这调用了我的 MapStore),然后我用它做了一些其他事情并调用了 service.update() ,最终在上面调用我的 doUpdate() 方法。此更新永远不会到达我的 MapStore,因此永远不会保留该值。当我使用替换方法 (replace(id, entity)) 的 2 arg 版本时,这些更改确实到达了 MapStore,因此被保留了下来。有什么区别,如何让它发挥作用?
编辑:添加 update() 方法:
public void update(NestupSecurityContext context, String id, @Validated T entity) throws ServiceException {
T existing = getOne(context, id);
if (existing != null) {
if (existing.equals(entity)) {
T copy;
try {
copy = (T) existing.clone();
} catch (CloneNotSupportedException e) {
//shouldn't be possible
throw new ServiceException(e);
}
copy.copyFrom(entity);
doUpdate(context, existing, copy);
} else {
throw new OptimisticConcurrencyServiceException(
entity.getEntityId() + " is out of date! Current version is " + existing.getVersion() + ", trying to save version " + entity.getVersion());
}
}
}
备注:
- equals() 检查版本,如上
- copyFrom() 是因为这些实体主要来自 REST 端点,并非所有值都可以通过 REST 端点设置。 copyFrom() 只复制可编辑的值,包括版本字段,当客户端在更新之前调用获取实体时必须携带该字段。
- clone() 为我们提供了该事务读取的基值的干净副本
这是我的 copyFrom() 没有调用父 class 来复制版本的问题。我还需要使我的 update() 方法 return 成为更新的实例(与原始实例不同),因此如果代码需要继续使用该对象,它可以使用更新的对象更新其引用。
我正在尝试按照 here 所述在 Hazelcast 中实施乐观并发检查。我已经将我的 MapConfigs 设置为使用 InMemoryFormat.OBJECT,并且我已经使用 equals() 和 hashCode() 向我的 BaseEntity 添加了一个版本字段,定义如下:
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
BaseEntity that = (BaseEntity) o;
return getId().equals(that.getId()) && getVersion() == that.getVersion();
}
@Override
public int hashCode() {
return (int) (getId().hashCode() + version);
}
在我的 BaseService 中,我将 map.replace(id, entity) 替换为 3 arg 版本,如下所示:
instance.incrementVersion();
if (getTransactionalMap().replace(instance.getId(), existing, instance)) {
// do some stuff here
} else {
throw new OptimisticConcurrencyServiceException(
"Could not replace existing " + existing.getEntityId() + " with version " + existing.getVersion());
}
我遇到的问题是更新时未调用我的 MapStore。在一次交易中,我创建了一个对象并通过我的 BaseService.create() 方法将其存储到地图(这调用了我的 MapStore),然后我用它做了一些其他事情并调用了 service.update() ,最终在上面调用我的 doUpdate() 方法。此更新永远不会到达我的 MapStore,因此永远不会保留该值。当我使用替换方法 (replace(id, entity)) 的 2 arg 版本时,这些更改确实到达了 MapStore,因此被保留了下来。有什么区别,如何让它发挥作用?
编辑:添加 update() 方法:
public void update(NestupSecurityContext context, String id, @Validated T entity) throws ServiceException {
T existing = getOne(context, id);
if (existing != null) {
if (existing.equals(entity)) {
T copy;
try {
copy = (T) existing.clone();
} catch (CloneNotSupportedException e) {
//shouldn't be possible
throw new ServiceException(e);
}
copy.copyFrom(entity);
doUpdate(context, existing, copy);
} else {
throw new OptimisticConcurrencyServiceException(
entity.getEntityId() + " is out of date! Current version is " + existing.getVersion() + ", trying to save version " + entity.getVersion());
}
}
}
备注:
- equals() 检查版本,如上
- copyFrom() 是因为这些实体主要来自 REST 端点,并非所有值都可以通过 REST 端点设置。 copyFrom() 只复制可编辑的值,包括版本字段,当客户端在更新之前调用获取实体时必须携带该字段。
- clone() 为我们提供了该事务读取的基值的干净副本
这是我的 copyFrom() 没有调用父 class 来复制版本的问题。我还需要使我的 update() 方法 return 成为更新的实例(与原始实例不同),因此如果代码需要继续使用该对象,它可以使用更新的对象更新其引用。