我正在尝试在Hazelcast中实现乐观并发检查,如here所述。我已经将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,因此值永远不会持久化。当我使用2方法版本的替换方法(替换(id,实体))时,这些更改确实到达了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());
}
}
}
备注:
答案 0 :(得分:1)
这是我的copyFrom()没有调用父类来复制版本的问题。我还需要让我的update()方法返回更新的实例(它与原始实例不同),因此如果代码需要继续使用该对象,它可以使用更新的对象更新其引用。