简体   繁体   English

JPA最佳实践,以使用集合更新实体

[英]JPA Best Practice to update an Entity with Collections

I am using JPA in a Glassfish Container. 我在Glassfish容器中使用JPA。 I have the following Modell (not complete) 我有以下Modell(不完整)

@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>();

This information will be updated daily. 此信息将每天更新。 Now my question is, what is the best practice to do this. 现在我的问题是,最佳做法是什么?

My fist approach was, I generate the Node Objects on the client (with LUNs) every day new, and merge it to the Database (I wanted to let JPA do the work) via service. 我的第一手方法是,我每天都会在客户端(带有LUN)上生成节点对象,然后通过服务将其合并到数据库(我想让JPA进行工作)。

Now I did some tests without LUNs yet. 现在我进行了一些没有LUN的测试。 I have the following service in a stateless EJB: 我在无状态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);
    }
}

The test: 考试:

@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);
}

This works without the @Version Field. 这在没有@Version字段的情况下有效。 With the @Version field I get an OptimisticLockException. 通过@Version字段,我得到了OptimisticLockException。

Is that the wrong approach? 那是错误的方法吗? Do I have to always perform an em.find(...) and then modify the managed entity via getter and setter? 我是否必须始终执行em.find(...),然后通过getter和setter修改托管实体?

Any help is appreciated. 任何帮助表示赞赏。

BR Rene 雷内

The @version annotation is used to enable optimistic locking. @version批注用于启用乐观锁定。

When you use optimistic locking, each successful write to your table increases a version counter, which is read and compared every time you persist your entities. 使用开放式锁定时,每次成功写入表都会增加一个版本计数器,每次您保留实体时都会对其进行读取和比较。 If the version read when you first find your entity doesn't match the version in the table at write time, an exception is thrown. 如果首次发现实体时读取的版本与写入时表中的版本不匹配,则会引发异常。

Your program updates the table several times after reading the version column only once. 您的程序仅读取一次version列后,会多次更新该表。 Therefore, at the second time you call persist() or merge(), the version numbers don't match, and your query fails. 因此,第二次您调用persist()或merge()时,版本号不匹配,并且查询失败。 This is the expected behavior when using optimistic locking: you were trying to overwrite a row that was changed since the time you first read it. 这是使用乐观锁定时的预期行为:您试图覆盖自首次读取以来已更改的行。

To answer your last question: You need to read the changed @version information after every write to your database. 要回答您的最后一个问题:每次写入数据库后,您需要阅读更改的@version信息。 You can do this by calling em.refresh(). 您可以通过调用em.refresh()来实现。

You should, however, consider re-thinking your strategy: Optimistic locks are best used on transactions, to ensure data consistency while the user performs changes. 但是,您应该考虑重新考虑策略:乐观锁最好用于事务,以确保用户执行更改时数据的一致性。 These usually read the data, display it to the user, wait for changes, and then persist the data after the user has finished the task. 这些通常读取数据,将其显示给用户,等待更改,然后在用户完成任务后保留数据。 You wouldn't really want nor need to write the same data rows several times in this context, because the transaction could fail due to optimistic locking on every one of these write calls - it would complicate things rather than make them more simple. 在这种情况下,您实际上并不需要多次写入相同的数据行,因为事务可能由于乐观地锁定这些写调用中的每一个而失败,这会使事情复杂化,而不是使事情变得更简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Hibernate更新实体最佳做法 - Hibernate update entity best practice JPA实体关系获取最佳实践 - JPA entity relation fetch best practice 在 JPA 中更新实体的最佳方法是什么 - What is the best way to update the entity in JPA JPA / Hibernate实体类和同步的最佳实践是什么? - What is the best practice for JPA/Hibernate entity classes and synchronization? 对JPA实体进行样本/预览更改的最佳实践 - Best Practice for Making Sample/Preview Changes to JPA Entity 在hibernate / jpa最佳实践问题中将分离的或新的实体与现有实体合并 - merging a detached or new entity with an existing entity in hibernate/jpa best practice question JPA - 渴望 - 懒惰的最佳实践 - JPA - Eager - Lazy best practice 在实体 class 包装器 class 或 JPA/Hibernate 中的原始类型中选择属性数据类型的最佳实践是哪一个? - Which one is the best practice for choosing data type of a property in entity class Wrapper class or Primitive type in JPA/Hibernate? Hibernate:Doman Model to JPA Entity / DTO&Merge()设计模式或最佳实践 - Hibernate: Doman Model to JPA Entity/DTO & Merge() Design pattern or best practice 最佳实践:JPA的最佳数据库命名约定? - Best practice: best database naming convention for JPA?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM