spring - Spring JPA休眠如何从@OneToMany父列中持久化子项(删除、添加或更新)?
问题描述
我一直在尝试解决这个问题,但我还没有达到 100% 的解决方案。首先,我必须描述我的问题。我正在开发一个餐厅应用程序,在实体中,我有实体成分,并且如您所知,成分可以由具有特定数量的其他成分组成。所以我创建了一个带有嵌入式 ID 的实体子成分。
为了坚持 subIngredients 列表,我尝试了 Cascade 和 orphanRemoval 的组合,每种组合都适用于某些操作,但不适用于其他操作。
我从使用 CascadeType.ALL 开始,并且新的 subIngredient 从 @OneToMany 属性中成功保留,但是如果我尝试从 subIngredients 列表中删除 subIngredient 并保存此错误,则会出现。
java.lang.StackOverflowError: null at com.mysql.cj.NativeSession.execSQL(NativeSession.java:1109) ~[mysql-connector-java-8.0.23.jar:8.0.23]......
我在网上寻找一个解决方案,我发现我必须使用 orphanremoval = true 我试过了,但是直到我将级联从 CascadeType.ALL 更改为 CascadeType.PERSIST 后它才起作用。但是这使得新的 SubIngredient 的持久性出现了这个错误
引起:javax.persistence.EntityNotFoundException:无法找到 com.example.Resto.domain.SubIngredient id 为 com.example.Resto.domain.SubIngredientKey@51b11186 ......
这些是我的实体:
@Entity
public class Ingredient {
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY)
@Column(name="ID")
private long id;
@NotNull
@Column(unique=true)
private String name;
private String photoContentType;
@Lob
private byte[] photo;
@JsonIgnoreProperties({"photoContentType","photo"})
@ManyToOne
private IngredientType ingredientType;
@OneToMany(mappedBy = "embId.ingredientId", fetch = FetchType.EAGER,
cascade = CascadeType.ALL /*or orphanRemoval = true, cascade = CascadeType.PERSIST*/ )
private Set<SubIngredient> subIngredients = new HashSet<SubIngredient>();
getters and setters.....
和
@Entity
@AssociationOverrides({
@AssociationOverride(name = "embId.ingredientId",
joinColumns = @JoinColumn(name = "ING_ID")),
@AssociationOverride(name = "embId.subIngredientId",
joinColumns = @JoinColumn(name = "SUB_ING_ID")) })
public class SubIngredient {
@EmbeddedId
private SubIngredientKey embId = new SubIngredientKey();
private double quantity;
getters and setters....
和
@Embeddable
public class SubIngredientKey implements Serializable{
@ManyToOne(cascade = CascadeType.ALL)
private Ingredient ingredientId;
@ManyToOne(cascade = CascadeType.ALL)
private Ingredient subIngredientId;
getters and setters...
解决方案
发生这种stackoverflow
情况是因为您使用了Set<>
with Hibernate
。当Hibernate
从您的数据库中检索实体时,它将填充Set<>
每个实体。为此,hashode/equals
将用于确定实体是否已经存在于Set<>
. 默认情况下,当您调用成分的哈希码时,会发生这种情况:
hashcode Ingredient -> hashcode SubIngredient -> hashcode Ingredient
这将导致方法的无限调用hashcode
。这就是为什么你有一个stackoverflow error
.
同样的事情也会发生equals/toString
。
所以为了避免这样的问题,最好覆盖hashcode
,equals
和toString
.
推荐阅读
- angular - 如何在 Angular2Csv 导出中设置字符编码?
- python - 解析存储在 Python Spark 中表列中的 JSON
- android - 如何保存应用程序在后台时收到的通知中的数据
- sorting - PHP Excel 自定义货币格式无法正确排序
- arrays - Excel合并2个公式
- spring-boot - 使用带有 JPA 实体更新的 @async 方法的 Spring Boot
- html - 超出指定宽度限制的打字动画 CSS
- amazon-web-services - 连接到 Kinesis 的 Pinpoint 与直接流式传输到 Kinesis 的移动应用程序有什么区别?
- python-3.x - 为什么我收到 ModuleNotFoundError: No module named 'grading' in Jupyiter notebook?
- javascript - 在 Javascript 中嵌套 If Else 语句