我搜索了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?
1 回答
你想要实现的是一个有点棘手的工作人员 . 如果延迟加载等不是一个选项(我更喜欢),我建议您创建另一个实体:
在此流程中,您必须检查父对象是否存在,并使用ChildSaveObject将其他子项保存到该对象中 .
在大多数情况下,我并不喜欢一对多的映射,我认为它们只是很多问题的根源 . 如果您更喜欢这种方式,我的建议是使用 fetch = FetchType.LAZY 并获取父实体(这样它就不会加载您不需要的所有子项) .