gpt4 book ai didi

java - Hibernate/JPA版本并发控制和DTO/更改命令模式

转载 作者:行者123 更新时间:2023-12-02 10:13:03 25 4
gpt4 key购买 nike

我想使用 @Version 与 JPA 和 Hibernate 进行乐观并发控制。

我知道它在两个并行事务的典型场景中是如何工作的。我还知道,如果我有一个在表单和实体之间具有 1:1 映射的 CRUD,我可以将 version 作为隐藏字段传递,并使用它来防止用户并发修改。

更有趣的案例(使用 DTO 或更改命令模式)怎么样?在这种情况下是否也可以使用@Version,以及如何使用?

让我举个例子。

@Entity
public class MyEntity {
@Id private int id;
@Version private int version;
private String someField;
private String someOtherField;
// ...
}

现在假设两个用户为此打开 GUI,进行一些修改并保存更改(不同时,因此事务不会重叠)。

如果我传递整个实体,第二个事务将失败:

@Transactional
public void updateMyEntity(MyEntity newState) {
entityManager.merge(newState);
}

这很好,但我不喜欢到处传递实体的想法,有时会使用 DTO、更改命令等。

为了简单起见,更改命令是一个映射,最终在某些服务上的调用中使用:

@Transactional
public void updateMyEntity(int entityId, int version, Map<String, Object> changes) {
MyEntity instance = loadEntity(entityId);
for(String field : changes.keySey()) {
setWithReflection(instance, field, changes.get(field));
}
// version is unused - can I use it somehow?
}

显然,如果两个用户打开我的 GUI,都进行更改,并依次执行,在这种情况下,两个更改都会应用,最后一个将“获胜”。我希望这个场景也能够检测并发修改(第二个用户应该得到一个异常)。

我怎样才能实现它?

最佳答案

如果我正确理解您的问题,您所需要的只是您的 private int version 字段的 setter ,当您更新实体时,您可以在实体中设置它。当然,您的 DTO 必须始终传输版本数据。最终,你还会做类似的事情:

MyEntity instance = loadEntity(entityId);
entityManager.detach(instance);
for(String field : changes.keySey()) {
setWithReflection(instance, field, changes.get(field));
}
//set also the version field, if the loop above does not set it
entityManager.merge(instance);

关于java - Hibernate/JPA版本并发控制和DTO/更改命令模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13194748/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com