Java 休眠删除非孤立子对象

Java 休眠删除非孤立子对象,java,hibernate,spring-data,Java,Hibernate,Spring Data,我正在使用Spring数据和Hibernate,CascadeType.ALL,以及orphanRemoving=true 问题是,当将子实体从parentX移动到parentY时,如果parentY在parentX之前被持久化,Hibernate将从数据库中完全删除该子实体。之后,孩子仍然存在于父母的记忆中。如果删除了它并保存了parentY,则会抛出一个EntityNotFoundException 我有一个SSCE演示了这一点,如有必要可以发布,但这似乎是一个简单的问题 母公司: @Ent

我正在使用Spring数据和Hibernate,
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 ...;