Java JPA双向一域关系-无法删除子项

Java JPA双向一域关系-无法删除子项,java,hibernate,jpa,Java,Hibernate,Jpa,在双向的“一对一”关系中,如何在不调用父对象的所有子对象的情况下删除子对象 因为我的应用程序有点太大了,所以我创建了一个示例项目来重现这个问题。我有两个实体,一个是父实体,一个是子实体 家长: package com.example.entity; import javax.persistence.*; import java.util.List; @Entity public class Parent { @Id @GeneratedValue(strategy = Gen

在双向的“一对一”关系中,如何在不调用父对象的所有子对象的情况下删除子对象

因为我的应用程序有点太大了,所以我创建了一个示例项目来重现这个问题。我有两个实体,一个是父实体,一个是子实体

家长:

package com.example.entity;

import javax.persistence.*;
import java.util.List;

@Entity
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(
        mappedBy      = "parent",
        cascade       = CascadeType.ALL,
        fetch         = FetchType.LAZY,
        orphanRemoval = true
    )
    private List<Child> children;
}
package com.example.entity;

import javax.persistence.*;

@Entity
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "parent_id")
    private Parent parent;
}
package com.example.dao;

import com.example.entity.Child;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ChildRepository extends JpaRepository<Child, Long> {}
package com.example;

import com.example.dao.ChildRepository;
import com.example.dao.ParentRepository;
import com.example.entity.Child;
import com.example.entity.Parent;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.transaction.Transactional;
import java.util.Arrays;

@RunWith(SpringRunner.class)
@SpringBootTest
public class RepositoryTest {
    @Autowired
    private ChildRepository childRepository;

    @Autowired
    private ParentRepository parentRepository;

    @Test
    @Transactional
    public void test() {
        Parent parent = new Parent();
        Child  child1 = new Child();
        Child  child2 = new Child();

        parent.setChildren(Arrays.asList(child1, child2));

        Assert.assertEquals(0, parentRepository.count());
        Assert.assertEquals(0, childRepository.count());

        parentRepository.save(parent);

        Assert.assertEquals(1, parentRepository.count());
        Assert.assertEquals(2, childRepository.count());

        childRepository.delete(child1);

        Assert.assertEquals(1, parentRepository.count());
        Assert.assertEquals(1, childRepository.count());
    }
}
未显示getter和Setter

我还有两个仓库:

ChildRepository:

package com.example.entity;

import javax.persistence.*;
import java.util.List;

@Entity
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(
        mappedBy      = "parent",
        cascade       = CascadeType.ALL,
        fetch         = FetchType.LAZY,
        orphanRemoval = true
    )
    private List<Child> children;
}
package com.example.entity;

import javax.persistence.*;

@Entity
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "parent_id")
    private Parent parent;
}
package com.example.dao;

import com.example.entity.Child;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ChildRepository extends JpaRepository<Child, Long> {}
package com.example;

import com.example.dao.ChildRepository;
import com.example.dao.ParentRepository;
import com.example.entity.Child;
import com.example.entity.Parent;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.transaction.Transactional;
import java.util.Arrays;

@RunWith(SpringRunner.class)
@SpringBootTest
public class RepositoryTest {
    @Autowired
    private ChildRepository childRepository;

    @Autowired
    private ParentRepository parentRepository;

    @Test
    @Transactional
    public void test() {
        Parent parent = new Parent();
        Child  child1 = new Child();
        Child  child2 = new Child();

        parent.setChildren(Arrays.asList(child1, child2));

        Assert.assertEquals(0, parentRepository.count());
        Assert.assertEquals(0, childRepository.count());

        parentRepository.save(parent);

        Assert.assertEquals(1, parentRepository.count());
        Assert.assertEquals(2, childRepository.count());

        childRepository.delete(child1);

        Assert.assertEquals(1, parentRepository.count());
        Assert.assertEquals(1, childRepository.count());
    }
}
但是,
子项
永远不会被删除,计数仍然是2!我读过很多关于同一个问题的问题,答案总是一样的:

parent.getChildren().remove(child1);
parentRepository.save(parent);
那不可能是这样做的吗?如果我的父母有数千个孩子,我必须让他们从数据库中全部删除一个?最尴尬的是,如果实体没有被删除,为什么他妈的不会抛出任何错误?那么正确的方法是什么呢?完全从父级中删除列表,并始终手动调用子级,以便没有外键?我从早餐开始就在努力解决这个问题,现在我在兜圈子

编辑:添加了休眠日志:

Hibernate: select count(*) as col_0_0_ from parent parent0_
Hibernate: select count(*) as col_0_0_ from child child0_
Hibernate: insert into parent (id) values (default)
Hibernate: insert into child (id, parent_id) values (default, ?)
Hibernate: insert into child (id, parent_id) values (default, ?)
Hibernate: select count(*) as col_0_0_ from parent parent0_
Hibernate: select count(*) as col_0_0_ from child child0_
Hibernate: select count(*) as col_0_0_ from parent parent0_
Hibernate: select count(*) as col_0_0_ from child child0_

该子对象是分离的实例(不是持久对象),如果进行调试,它不应该有id

我的问题是,为什么创建新对象只是为了删除它?如果可以确定在持久化之前将删除哪个子级,为什么不将其从添加中排除(
Arrays.asList(child1,child2)


或者,如果您只能在该子对象持久化后才能确定,这意味着您有办法获取该子对象的持久化实例1,这样您就可以删除该对象而不会遇到此类问题。

该子对象是分离的实例(而非持久化对象),如果您进行调试,则该子对象不应具有其id

我的问题是,为什么创建新对象只是为了删除它?如果可以确定在持久化之前将删除哪个子级,为什么不将其从添加中排除(
Arrays.asList(child1,child2)


或者,如果您只能在该对象持久化后才能确定,这意味着您有办法获得该子对象的持久化实例1,这样您就可以删除该对象,而不会遇到此类问题。

问题在于您在一个事务中执行该操作。如果您结束事务并检查数据库,则删除应该有效。@ByeBye nope快速测试了它,正如您从添加的hibernate日志中看到的,删除ist从未触发。因为您的child1实体与这个新创建的实体没有连接。在
childRepository.delete(child1)
只是一个空的实体。问题是您在一个事务中完成了它。如果您结束事务并检查数据库,则删除应该有效。@ByeBye nope快速测试了它,正如您从添加的hibernate日志中看到的,删除ist从未触发。因为您的child1实体与这个新创建的实体没有连接。在
childRepository.delete(child1)
只是一个空实体。