繁体   English   中英

Spring JPA从新的子实体合并父实体

[英]Spring JPA merge parent entity from new child entity

我搜索了SO并没有为此找到合适的解决方案。 假设我有一个父实体:

@Entity
public class Parent {
    @Id
    @GeneratedValue
    private int id;

    @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE)
    private List<Child> childList;
}

和子实体,它具有与父实体关联的外键:

@Entity
public class Child {
    @Id
    @GeneratedValue
    private int id;

    @JoinColumn(name = "parentId")
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private Parent parent;

}

我的场景有点特别。 子实体每小时生成一次,我需要将它们保存到数据库中。 这些子对象可以具有相同的父对象,并且关联父实体可能已经存在于数据库中。 我的要求是保存所有这些子对象而不从entityManager中查询托管父实体,如果父实体存在,则只需合并/更新现有实体。 如:

Child c = new Child();
// set some properties of child
Parent p = new Parent();
// set some properties from my data into the parent. The parent may already exists
child.setParent(p);
JpaRepo.saveAndFlush(child);// If parent already exists, merge with the existed parent object, otherwise, create new parent object.

显然这不起作用。 当父实体不存在时,它将正确创建父实体并与之关联。 但是如果父元素已经存在,它将抛出关于重复键的异常,如果我设置父元素的Id(使用虚拟值强制使其通过合并),它将抛出分离的实体对象的异常。

由于性能限制,我无法从数据库加载父实体,因为它们太多了。 那么当主键违反时,有没有办法自动为JPA或数据库合并对象?

我正在使用MySQL,是否可以使用ON DUPLICATE KEY UPDATE?

你想要实现的是一个有点棘手的工作人员。 如果延迟加载等不是一个选项(我更喜欢),我建议您创建另一个实体:

@Entity
@Table(name = "sameAsTheOriginal")
public class ChildSaveObject {
    @Id
    @GeneratedValue
    private int id; //I think int will run out fast if there are a lot of objects but it is your choice. (Int max value: 2 147 483 647 is not that mutch) I prefer Long az id

    @Column(name = "parentId")
    private int parent; //note that You need to have the id of the parent object

    //Other properties...
}

在此流程中,您必须检查父对象是否存在,并使用ChildSaveObject将其他子项保存到该对象。

在大多数情况下,我并不喜欢一对多的映射,我认为它们只是很多问题的根源。 如果您更喜欢这种方式,我建议使用fetch = FetchType.LAZY并获取父实体(这样它就不会加载您不需要的所有子项)。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM