繁体   English   中英

JPA双向OneToMany关系 - 不能删除孩子

[英]JPA bidirectional OneToMany relashionship - cant delete child

在双向OneToMany关系中,如何在不调用父项具有的所有子项的情况下删除子项?

由于我的应用程序有点大,我创建了一个示例项目来重新创建问题。 我有2个实体,一个父母和一个孩子。

家长:

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;
}

Getters和Setter没有显示!

儿童:

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;
}

Getters和Setter没有显示!

我还有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日志:

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。

我的问题是为什么你创建新对象只是为了删除它? 如果您可以确定在保留之前将删除哪个子项,为什么不将它从add( Arrays.asList(child1, child2) )中排除?

或者如果你只能在它持久化之后确定,那意味着你有办法获得那个child1的持久化实例,这样你就可以删除这个对象而不会遇到这种问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM