【发布时间】:2022-01-11 11:49:09
【问题描述】:
亲爱的 StackOverflow 社区,您好, 我最近遇到了一个问题,我无法将已保存对象的引用放入其中。我不想保存或更新对象,因为这些对象已预先插入到我们的数据库中。
所以基本上我的情况如下: 我有一个父母,在这种情况下,它是一个 Intake,并且该对象有一个 IntakeTimes 列表,它们被声明为 remainingDoses。有道理,呵呵。
当在剩余剂量上使用 CascadeType.MERGE 时,我实际上能够保存 ChildDisease 对象(我实际保存的最上面的父对象),但是如果在其 Intake 对象上存在具有此类 IntakeTime 的已保存 ChildDisease,我收到“键 'X' 的重复条目 'X'”错误。
在剩余剂量上使用 CascadeType.PERSIST 时,我得到“传递给持久化的分离实体:com.x.x.entity.IntakeTime”
我的模型如下所示:
ChildDisease.java(最高父级)
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name="child_disease")
public class ChildDisease extends BaseEntity {
@ManyToOne(cascade = CascadeType.DETACH)
@JoinColumn(name="child_Fk")
private Child child;
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name="disease_Fk")
private Disease disease;
@OneToOne(cascade = CascadeType.PERSIST, orphanRemoval = true, fetch=FetchType.EAGER)
@JoinColumn(name = "medication_decree_Fk")
private MedicationDecree medicationDecree;
}
MedicationDecree.java(ChildDisease.java 的直接子代)
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table
public class MedicationDecree extends BaseEntity {
@Column
private float consumptionAmount;
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private MeasuringUnit measuringUnit;
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name="medication_Fk")
private Medication medication;
@OneToOne(cascade = CascadeType.PERSIST)
private Intake intake;
@ManyToMany(cascade = CascadeType.MERGE)
private List<IntakeTime> intakeTimes;
}
Intake.java(ChildDisease.java 的直接子代)
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Intake extends BaseEntity {
@OneToMany(cascade = CascadeType.MERGE)
public List<IntakeTime> remainingDoses;
@Column
public Date date;
}
我期待任何帮助或提示,感谢社区。p>
【问题讨论】:
-
您能否添加完整的代码以重现例如 MERGE 案例,以显示您在保存之前如何初始化所有实体?
-
不清楚您正在使用哪些 JPA 方法、持久化或合并,以及各种级联类型的操作。在这 4 个实体类型图中也不清楚,哪些是新的,哪些是现有的,或者为什么在不同级别有不同的级联合并操作。 ChildDisease->MedicationDecree-> Intake all 使用 cascade persist,而 MedicationDecree->IntakeTime 和 Intake-> IntakeTime 使用 cascade merge。如果您只使用存在的 ChildDiseases,则合并不会选择 MedicationDecree。如果使用持久化,它不会获取任何引用的 IntakeTime。
-
听起来您正在创建引用图中现有 IntakeTime 实例的新父级,并调用persist。您必须从当前 EnityManager 上下文中查找那些现有的 IntakeTime 实例,并在 ChildDisease 中使用这些引用。也许在设置这些引用之前坚持 ChildDisease,然后在之后修复/保存 ChildDisease。仅查找它们不会强制更新它们
-
好的开始,但要重现问题,还需要所有映射器代码和真实数据。在minimal form 中。然后您可能会自己发现问题。
-
你为什么在intakeTime.getId 值中暂停时调用existsById - 这是在你的测试中从findbyId 切换而来的吗?它们需要添加到集合中并设置在集合中,但您还必须检查 MedicationDecree.intakeTimes 集合。但是您发现了问题 - 您已将 Intake-> IntakeTime 映射为 OneToMany,并且您的表只允许每次 Intake 有一个 IntakeTime。您要么需要更正引用现有 IntakeTime 的现有 Intake,以便只有一个引用它,要么将表/映射更改为 ManyToMany。