在双向OneToMany关系中,如何在不调用父母所有孩子的情况下删除孩子?JPA双向OneToMany接力 - 不能删除孩子
由于我的应用程序有点大,我创建了一个示例项目来重新创建问题。我有两个实体,一个父母和一个孩子。
家长:
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;
}
getter和二传手未显示!
儿童:
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;
}
getter和二传手未显示!
我也有2个Repositorys:
ChildRepository:
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> {}
ParentRepsitory:长得一模一样。
现在,我创建了一个测试来重现问题:
RepositoryTest:
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());
}
}
然而Child
将永远不会被删除,计数将仍然是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_
问题是,你正在做一个事务。如果您结束您的交易并检查数据库删除应该有效。 – ByeBye
@ByeBye nope很快就对它进行了测试,正如你从添加的hibernate日志中看到的那样,一个删除ist永远不会被触发。 – daputzy
因为你的child1实体与这个新创建的没有关系。在'childRepository.delete(child1)'时刻只是空的实体。 – ByeBye