如何在标有CascadeType.ALL的关系中添加持久实体? [英] How to add persisted entities in a relationship marked with CascadeType.ALL?

查看:86
本文介绍了如何在标有CascadeType.ALL的关系中添加持久实体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an Entity with a bidirectional ManyToMany relationship (on the same entity) marked as 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>();

我在服务器端有一种方法可以保存此实体:

I have a method on the server side supposed to do save this entity:

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

如果联系人 children 列表中的任何实体都不保留。但是有时我需要对已经持久化的实体使用 saveContact 方法,当我尝试执行此操作时,似乎JPA试图持久化关系的所有实体,并且然后将引发异常:

It works great if the contact or any entities of the childs list are not persisted. But sometimes i will need to use the saveContact method with already persisted entities, and when i try to do this, it seems like JPA try to persist all the entities of the relationship and then will raise the exception:

Internal Exception: java.sql.SQLIntegrityConstraintViolationException

实际上,它会尝试重新存储并已经存在的实体,因此 Contact 将被违反。

Indeed, it'll try to repersist and already persisted entity, so the unicity of the ID field of Contact will be violated.

如何激活它?我的方法有什么问题?

How can active this? What's wrong with my approach?

我如何使Eclipselink / JPA不尝试保留关系中已经存在的实体? / strong>

How can i make Eclipselink/JPA does not try to persist entities that are part of the relationship and that are already persisted?

推荐答案

如果您的父联系人实体是新实体,但有些子实体存在(但已分离),则您不会要在父级上调用持久化-这将导致持久化级联到子级,这需要立即或在刷新/提交时引发异常。如果您希望对新的父联系人打电话给perist,那么您应该尝试查找现有的孩子并将托管实例与新的联系人关联。如果不存在,则可以单独保留该孩子,也可以允许其在关系上进行级联以为您完成该工作。

If your parent contact Entity is new but some of the children exist (but are detached), you do not want to call persist on the parent - this will cause the persist to cascade to the children which is required to cause an exception to be thrown either immediately or on the flush/commit. If you wish to call perist on the new parent contact, then you should try to find the existing children and associate the managed instances to the new contact. If it doesn't exist, you can persist the child individually or allow persist to cascade over the relationship to do it for you.

通常,这样做会容易得多调用新的父联系人上的合并,并让提供者确定是更新还是插入。由于将合并级联传递给子级,因此也会适当地插入或更新它们。

Generally though, it is much easier just to call merge on the new parent contact and have the provider figure out if it should be an update or an insert. Since merge cascades to the children, they too will be inserted or updated as appropriate.

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

Be careful with the use of cascading though. When you go to remove a parent, it will also cascade the remove to the children, which then cascades to every parent in their parent collections. If it is not managed correctly, it could remove all contacts unintentionally. Also note that changes that cause a child to be removed from the list might not cascade correctly - cascade merge can only operate on entities that are currently in the collection, not ones that used to be there. So you may need to manually call merge on children when removing them from the parent's collection or ensure they have merged called through a different path.

这篇关于如何在标有CascadeType.ALL的关系中添加持久实体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆