gpt4 book ai didi

java - 如何在标有 CascadeType.ALL 的关系中添加持久实体?

转载 作者:行者123 更新时间:2023-11-30 04:36:02 25 4
gpt4 key购买 nike

我有一个 Entity,其双向 ManyToMany 关系(在同一实体上)标记为 CascadeType.ALL

以下是查找 Contact 实体的方式:

@ManyToMany(cascade= CascadeType.ALL)
private List<Contact> parentContacts = new ArrayList<Contact>();
@ManyToMany(cascade= CascadeType.ALL, mappedBy="parentContacts")
private List<Contact> childContacts = new ArrayList<Contact>();

我在服务器端有一个方法应该保存这个实体:

public AltContact saveContact(EntityManager em, Contact contact, List<Contact> childs) {
for (Contact c : childs) {
contact.getChildContacts().add(c);
c.getParentContacts().add(contact);
}
if (contact.getId() == null) {
em.persist(contact);
} else {
contact = em.merge(contact);
}
return contact;
}

如果 contactchilds 列表中的任何实体未保留,效果会很好。但有时我需要对已经持久化的实体使用 saveContact 方法,当我尝试这样做时,似乎 JPA 尝试持久化关系的所有实体,然后会引发异常:

Internal Exception: java.sql.SQLIntegrityConstraintViolationException

事实上,它会尝试重新持久化已经持久化的实体,因此Contact的ID字段的唯一性将被违反。

如何激活这个?我的方法有什么问题吗?

我怎样才能使 Eclipselink/JPA 不尝试持久化属于关系一部分并且已经持久化的实体?

最佳答案

如果您的父联系人实体是新的,但某些子实体存在(但已分离),您不希望在父实体上调用 persist - 这将导致 persist 级联到子实体,这是导致异常所必需的立即抛出或在刷新/提交时抛出。如果您希望对新的父联系人调用 perist,则应尝试查找现有的子联系人并将托管实例关联到新联系人。如果它不存在,您可以单独保留子项,或者允许保留级联关系来为您完成此操作。

一般来说,对新的父联系人调用合并并让提供程序确定它是否应该更新或插入要容易得多。由于合并级联到子级,因此它们也将根据需要插入或更新。

不过,请谨慎使用级联。当您删除父级时,它还会将删除级联到子级,然后级联到其父级集合中的每个父级。如果管理不当,可能会无意中删除所有联系人。另请注意,导致子项从列表中删除的更改可能无法正确级联 - 级联合并只能对当前位于集合中的实体进行操作,而不能对曾经存在的实体进行操作。因此,当您从父级集合中删除子级时,您可能需要手动调用合并,或者确保它们已通过不同的路径进行合并调用。

关于java - 如何在标有 CascadeType.ALL 的关系中添加持久实体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13513927/

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