当我有一个具有关系的实体时,我不知道哪种是将更改保存到数据库的最佳方法。
这是一个简化的实体。请考虑一下,我对代码进行了一些更改,以便将其发布到此处,并且我可能会引入一些错误。
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 个实体。 我将 Glassfish 与 jta 结合使用,因此事务和实体管理器由容器管理。
有一次,我的内存中有一个独立的(JPA 术语)Permessitetemporanei 实例。 我必须将以下更改保留到数据库: 1- 必须删除关联的 ingressiconpermesso 2- 必须创建一个新的 ingressiconpermesso 3- statopermesso 字段必须更新 4- 必须将新的 Accessiconpermesso 添加到集合 accessiconpermessoCollection
最好的方法是什么?也许我可以在 Permessitemporanei 实例中进行所有必要的更改并将其合并,但这样做时遇到了很多麻烦,并开始认为持久更改不是关系的右侧。 对我来说,一次保存一个对象更自然,因此消除所有那些级联 = CascadeType.ALL。
假设我的 Permessitemporanei 实例名为“permesso”;我的代码是这样的:
- getEntityManager().remove(permesso.ingressiconpermesso);
- getEntityManager().persist(一个新的 Ingressiconpermesso );
- getEntityManager().merge(permesso)//一旦其 statopermesso 字段已更新;
- getEntityManager().perist(一个新的 Accessiconpermesso );
显然,这样我必须使用我对数据库所做的所有更改手动更新内存中的“permesso”。
有更好的方法吗?
顺便说一句,我见过的所有 JPA 关系都是双向的。我可以让它们单向吗?换句话说,我可以安全地消除吗? 代码:
@OneToMany(级联= CascadeType.ALL,mappedBy =“iDpermesso”) 私有(private)集合 accessiconpermessoCollection;
来自 Permessitetemporanei 实体,将其保留在 Accessiconpermesso 实体上,还是会破坏 JPA?
谢谢 菲利波
最佳答案
我喜欢处理复杂实体更新的方式是:
- 开始新交易。
- 对内存中的对象进行我想要进行的所有更改。
- 完成后告诉
EntityManager
我做了什么。 - 提交交易。
但首先,如果您从一个非分离的 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 映射当然会破坏任何此类代码)。然而,我真的不认为删除它会带来任何好处,所以我建议不要管它。
关于java - 在关系中使用 JPA 的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6897961/