gpt4 book ai didi

java - 使用集合更新实体的 JPA 最佳实践

转载 作者:行者123 更新时间:2023-12-01 15:58:11 24 4
gpt4 key购买 nike

我在 Glassfish 容器中使用 JPA。我有以下模型(不完整)

@Entity
public class Node {
@Id
private String serial;
@Version
@Column(updatable=false)
protected Integer version;
private String name;
@ManyToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE})
private Set<LUN> luns = new HashSet<LUN>();

@Entity
public class LUN {
@Id
private String wwid;
@Version
@Column(updatable=false)
protected Integer version;
private String vendor;
private String model;
private Long capacity;
@ManyToMany(mappedBy = "luns")
private Set<Node> nodes = new HashSet<Node>();

此信息将每天更新。现在我的问题是,执行此操作的最佳实践是什么。

我的第一个方法是,我每天在客户端上生成新的节点对象(带有 LUN),并通过服务将其合并到数据库(我想让 JPA 来做这项工作)。

现在我做了一些没有 LUN 的测试。我在无状态 EJB 中有以下服务:

public void updateNode(Node node) {
if (!nodeInDB(node)) {
LOGGER.log(Level.INFO, "persisting node {0} the first time", node.toString());
em.persist(node);
} else {
LOGGER.log(Level.INFO, "merging node {0}", node.toString());
node = em.merge(node);
}
}

测试:

@Test
public void addTest() throws Exception {
Node node = new Node();
node.setName("hostname");
node.setSerial("serial");
nodeManager.updateNode(node);
nodeManager.updateNode(node);
node.setName("newhostname");
nodeManager.updateNode(node);
}

这无需 @Version 字段即可工作。使用 @Version 字段,我得到一个 OptimisticLockException。

这是错误的做法吗?我是否必须始终执行 em.find(...),然后通过 getter 和 setter 修改托管实体?

感谢任何帮助。

BR雷内

最佳答案

@version 注解用于启用乐观锁定。

当您使用乐观锁定时,每次成功写入表都会增加一个版本计数器,每次持久化实体时都会读取并比较该计数器。如果您第一次发现实体时读取的版本与写入时表中的版本不匹配,则会引发异常。

您的程序在仅读取一次版本列后多次更新该表。因此,在第二次调用 persist() 或 merge() 时,版本号不匹配,查询失败。这是使用乐观锁定时的预期行为:您试图覆盖自第一次读取以来已更改的行。

回答你的最后一个问题:每次写入数据库后,你都需要读取更改后的@version信息。您可以通过调用 em.refresh() 来完成此操作。

但是,您应该考虑重新考虑您的策略:乐观锁最好在事务上使用,以确保用户执行更改时数据的一致性。这些通常读取数据,将其显示给用户,等待更改,然后在用户完成任务后保留数据。在这种情况下,您实际上并不希望也不需要多次写入相同的数据行,因为事务可能会由于每一个写入调用上的乐观锁定而失败 - 这会使事情变得复杂而不是让它们变得更简单。

关于java - 使用集合更新实体的 JPA 最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4616494/

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