使用JPA与关系的最佳方式

时间:2011-08-01 11:47:02

标签: java jsf jpa netbeans ejb

当我有一个有关系的实体时,我不知道哪种方法可以保存对DB的更改。

这是一个简化的实体。请考虑我对代码进行了少量更改,以便在此处发布,我可以介绍一些错误。

public class Permessitemporanei implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "ID_permesso")
    private Integer iDpermesso;
    @Column(name = "Stato_permesso")
    private Integer statopermesso;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "iDpermesso")
    private Collection<Accessiconpermesso> accessiconpermessoCollection;
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "iDpermesso")
    private Ingressiconpermesso  ingressiconpermesso;

正如您所看到的,它与具有OneToMany和OneToOne关系的其他2个实体相关联。 我正在使用带有jta的Glassfish,因此事务和entityManagers由容器管理。

此时我在内存中有一个分离的(JPA术语)Permessitemporanei实例。 我必须坚持对数据库进行以下更改: 1-必须删除相关的ingressiconpermesso 2-必须创建一个新的ingressiconpermesso 必须更新3- statopermesso字段 4-必须将新的Accessiconpermesso添加到集合accessiconpermessoCollection

这是最好的方法吗?也许我可以在Permessitemporanei实例中进行所有必要的更改并合并它但是我有很多麻烦这样做并且开始认为持续变化不是关系的右侧。 对我来说,一次保存一个对象更自然,因此消除所有那些cascade = CascadeType.ALL。

假设我的Permessitemporanei实例被称为'permesso';我的代码是这样的:

  1. getEntityManager()除去(permesso.ingressiconpermesso);
  2. getEntityManager()。persist(一个新的Ingressiconpermesso);
  3. getEntityManager()。merge(permesso)//一旦更新了statopermesso字段;
  4. getEntityManager()。perist(一个新的Accessiconpermesso);
  5. 显然,这种方式我必须手动更新内存'permesso'以及我在数据库上所做的所有更改。

    有更好的方法吗?

    顺便说一下,我看到的所有JPA关系都是双向的。我可以让它们单向吗?换句话说,我可以安全地消除 代码:

    @OneToMany(cascade = CascadeType.ALL,mappedBy =“iDpermesso”)     私人收藏accessiconpermessoCollection;

    来自Permessitemporanei实体的

    在Accessiconpermesso实体上保留它还是打破JPA?

    由于 菲利普

1 个答案:

答案 0 :(得分:3)

我喜欢处理复杂实体更新的方式是:

  1. 开始新的交易。
  2. 在内存中对我的对象进行所有更改。
  3. 告诉EntityManager一旦我完成了我做了什么。
  4. 提交交易。
  5. 但首先,如果你得到一个非分离的Permessitemporanei实例,你可能会有更容易的时间:

    Permessitemporanei persistentInstance = em.find(Permessitemporanei.class, detachedInstance.getId());
    

    然后在内存中进行所有更改,通知EntityManager,然后提交事务:

    //begin a transaction
    em.getTransaction().begin();
    
    //remember the old Ingressiconpermesso instance
    Ingressiconpermesso oldIngression = persistentInstance.getIngressiconpermesso();
    
    //create a new Ingressiconpermesso instance
    Ingressiconpermesso newIngression = new Ingressiconpermesso();
    //call newIngression.set...() methods here
    
    //associate the new Ingressiconpermesso with the Permessitemporanei 
    persistentInstance.setIngressiconpermesso(newIngression);
    
    //update statopermesso
    persistentInstance.setStatopermesso(7); //replace '7' with whatever the real value is
    
    //add a new Accessiconpermesso
    Accessiconpermesso accession = new Accessiconpermesso();
    //call accession.set...() methods here
    
    //associate the Accessiconpermesso with the Permessitemporanei
    accession.setPermissitemporanei(persistentInstance);
    
    //now tell the EntityManager what we did
    em.remove(oldIngression);        //delete the old Ingressiconpermesso 
    em.persist(newIngression);       //add the new Ingressiconpermesso 
    em.persist(accession);           //add the Accessiconpermesso
    em.merge(persistentInstance);    //update the Permessitemporanei
    
    //commit the transaction
    em.getTransaction().commit();
    

    要回答您的其他问题,不,您通常不需要注释关系的两个方面。如果你愿意,你可以删除你的@OneToMany注释,它不应该破坏任何东西(就JPA而言,无论如何......你可能会有依赖于Collection存在的应用程序代码和正确填充,删除JPA映射当然会破坏任何此类代码)。但是,我真的不认为你通过移除它获得任何东西,所以我建议不要管它。