我认为我的休眠数据库设置不正确。我有Citizen
个实体,它们与WeeklyCare
个实体具有一对多的关系。以下是相关代码。
公民:
@Entity
@Table(name = "citizens")
public class Citizen {
@Id
@Size(max = 10, min = 10, message = "CPR must be exactly 10 characters")
private String cpr;
@OneToMany()
@JoinColumn(name = "cpr")
private List<WeeklyCare> weeklyCare;
}
每周护理:
@Entity
public class WeeklyCare {
@EmbeddedId
private WeeklyCareIdentifier weeklyCareIdentifier;
}
WeeklyCareIdentifier:
@Embeddable
public class WeeklyCareIdentifier implements Serializable {
@NotNull
@Size(max = 10, min = 10, message = "CPR must tbe exactly 10 characters")
private String cpr;
@NotNull
private Integer week;
@NotNull
private Integer year;
}
我想将数据保存到数据库时遇到一些问题:
我不能先保存
WeeklyCare
,因为它需要一个Citizen
。当我将市民发送到我的后端时,对象包含
WeeklyCare
列表。当我尝试保存市民时,它给了我这个错误:Unable to find Application.Models.WeeklyCare with id Application.Models.WeeklyCareIdentifier@b23ef67b
我可以通过在保存之前清除
WeeklyCare
上的Citizen
列表,然后在保存之后再保存WeeklyCare
列表的方式来解决此问题,但这听起来像是一种糟糕的方法。我想我想让休眠状态在保存
WeeklyCare
时忽略Citizen
的列表,但在获取Citizen
时确认它。这可能吗?还是有更好的方法呢?谢谢。 最佳答案
我不能先保存WeeklyCare,因为它需要一个公民。
您在两个实体中使用了“ cpr”标识符:
这是Citizen
的主要ID
它是WeeklyCare
复合ID的一部分
从理论上讲,您可以创建WeeklyCare
的列表(尽管现在不采用它的建模方式),然后再将每个WeeklyCare
的关联更新为Citizen
。
当我将市民发送到我的后端时,这些对象包含WeeklyCare的列表。当我试图拯救公民时,它给了我
错误:找不到ID为Application.Models.WeeklyCare
应用程序。模型.WeeklyCareIdentifier @ b23ef67b
映射一对多关联的最佳方法是双向。这也将使您免于仅在将@OneToMany与@JoinColumn一起使用时Hibernate生成的一些不必要的查询。
1)从WeeklyCareIdentifier
类中删除cpr(并可能重命名该类)。
@Embeddable
public class WeeklyCareIdentifier implements Serializable {
@NotNull
private Integer week;
@NotNull
private Integer year;
//constructors, getters, setters
}
2)删除复合@EmbeddedId以支持Long id字段:
@Entity
public class WeeklyCare {
@Id
@GeneratedValue
private Long id;
@Embedded
private WeeklyCareIdentifier weeklyCareIdentifier;
//constructors, getters, setters
}
3)移至双向映射:
@Entity
@Table(name = "citizens")
public class Citizen {
@Id
@Size(max = 10, min = 10, message = "CPR must be exactly 10 characters")
private String cpr;
@OneToMany(
mappedBy = "citizen",
cascade = CascadeType.ALL, //cascade all operations to children
orphanRemoval = true //remove orphaned WeeklyCare if they don't have associated Citizen
)
private List<WeeklyCare> weeklyCares = new ArrayList<>(); //init collections to avoid nulls
//constructors, getters, setters
//add utility methods to manipulate the relationship
public void addWeeklyCare(WeeklyCare weeklyCare) {
weeklyCares.add(weeklyCare);
weeklyCare.setCitizen(this);
}
public void removeWeeklyCare(WeeklyCare weeklyCare) {
weeklyCares.remove(weeklyCare);
weeklyCare.setCitizen(null);
}
}
和:
@Entity
public class WeeklyCare {
@Id
@GeneratedValue
private Long id;
//having reference to the citizen entity from WeeklyCare
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "citizen_cpr")
private Citizen citizen;
@Embedded
private WeeklyCareIdentifier weeklyCareIdentifier;
//constructors, getters, setters
}
即使cpr是唯一的,我也建议对实体使用Long ID。将cpr转换为普通列,并引入一个DB生成的ID列,您可以在内部域中使用该列将其与之连接,并将cpr视为纯面向用户的数据列。