Java 休眠删除非孤立子对象
我正在使用Spring数据和Hibernate,Java 休眠删除非孤立子对象,java,hibernate,spring-data,Java,Hibernate,Spring Data,我正在使用Spring数据和Hibernate,CascadeType.ALL,以及orphanRemoving=true 问题是,当将子实体从parentX移动到parentY时,如果parentY在parentX之前被持久化,Hibernate将从数据库中完全删除该子实体。之后,孩子仍然存在于父母的记忆中。如果删除了它并保存了parentY,则会抛出一个EntityNotFoundException 我有一个SSCE演示了这一点,如有必要可以发布,但这似乎是一个简单的问题 母公司: @Ent
CascadeType.ALL
,以及orphanRemoving=true
问题是,当将子实体从parentX移动到parentY时,如果parentY在parentX之前被持久化,Hibernate将从数据库中完全删除该子实体。之后,孩子仍然存在于父母的记忆中。如果删除了它并保存了parentY,则会抛出一个EntityNotFoundException
我有一个SSCE演示了这一点,如有必要可以发布,但这似乎是一个简单的问题
母公司:
@Entity
public class TestParent implements Serializable {
private static final long serialVersionUID = 3572015072906463953L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TestParent_GENERATOR")
@SequenceGenerator(name = "TestParent_GENERATOR", initialValue = 1, sequenceName = "TestParent_SEQUENCE", allocationSize = 1)
private long id;
private String name;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
@JoinColumn(name = "TestParent_Id")
private Set<TestChild> testChildren = new HashSet<>();
@SuppressWarnings("unused")
private TestParent() {
}
public TestParent(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void addChild(TestChild child) {
this.testChildren.add(child);
}
public void removeChild(TestChild child) {
this.testChildren.remove(child);
}
public TestChild findChild(String childsName) {
for (TestChild testChild : this.testChildren) {
if (testChild.getName().equals(childsName)) {
return testChild;
}
}
return null;
}
}
从Hibernate的角度来看,实体映射是不完整的,这就是您可能会得到意外结果的原因。最大的罪魁祸首是
orphaneremovation=true
,它在使用时没有使用mappedBy=…
。尽管JPA规范不要求使用orphandremovation=true
指定mappedBy=…
,但如果未指定mappedBy=…
,Hibernate很难确定一对多关联的many
端的实体是否真的是孤立的
以下映射将更正该行为:
class TestParent {
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "testParent")
private Set<TestChild> testChildren = new HashSet<TestChild>();
}
class TestChild {
@JoinColumn(name = "TestParent_Id")
@ManyToOne
private TestParent testParent;
}
如果以
mvn clean test
的形式运行单元测试,您将看到SQL查询按预期执行。请提供实体的代码。TestChild
是否与TestParent
有关联(可能通过一个字段)?发布的代码没有显示任何这种关系。@Eruza,你能检查我下面答案中链接的示例应用程序吗?
class TestParent {
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "testParent")
private Set<TestChild> testChildren = new HashSet<TestChild>();
}
class TestChild {
@JoinColumn(name = "TestParent_Id")
@ManyToOne
private TestParent testParent;
}
INSERT INTO parent (...) VALUES (...);
INSERT INTO child (...) VALUES (...);
INSERT INTO parent (...) VALUES (...);
UPDATE child SET ...;