Spring Boot 当JPA中没有CASCADE的情况下,将“删除”设置为true时从列表中删除的问题

v8wbuo2f  于 2023-10-16  发布在  Spring
关注(0)|答案(1)|浏览(110)

Gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.3'
    id 'io.spring.dependency-management' version '1.1.3'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '17'
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testCompileOnly 'org.projectlombok:lombok'
    testAnnotationProcessor 'org.projectlombok:lombok'
}

tasks.named('test') {
    useJUnitPlatform()
}

实体

@Entity
@Getter
@Setter
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "member_id")
    private Long id;
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    private Parent parent;
}
@Entity
@Getter
@Setter
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "member_id")
    private Long id;
    private String name;
    @OneToMany(mappedBy = "parent", orphanRemoval = true)
    private List<Child> childList = new ArrayList<>();

    public void addChild(Child child){
        childList.add(child);
        child.setParent(this);
    }
}

测试代码

@Test
@Transactional
@Rollback(value = false)
void name() {
    Child child1 = new Child();
    child1.setName("child1");

    Parent parent = new Parent();
    parent.addChild(child1);

    em.persist(parent);
    em.persist(child1);

    em.flush();
    em.clear();

    Parent findParent = em.find(Parent.class, parent.getId());

    findParent.getChildList().remove(0);
    //em.remove(findParent);
}

日志

Hibernate: 
    /* insert for
        com.example.jpa.domain.Parent */insert 
    into
        parent (name) 
    values
        (?)
Hibernate: 
    /* insert for
        com.example.jpa.domain.Child */insert 
    into
        child (name,parent_id) 
    values
        (?,?)
Hibernate: 
    select
        p1_0.member_id,
        p1_0.name 
    from
        parent p1_0 
    where
        p1_0.member_id=?
Hibernate: 
    select
        c1_0.parent_id,
        c1_0.member_id,
        c1_0.name 
    from
        child c1_0 
    where
        c1_0.parent_id=?

我现在是一名学习JPA的学生。在研究孤立对象删除设置时,我注意到当我不设置CASCADE时,删除父对象本身会删除实际数据库中的子对象。然而,当我从父列表中删除子列表时,JPA似乎没有检测到这种变化。
从我所学到的,当父对象和子对象之间的关联被破坏时,子对象应该被删除。那么,当我从父列表中删除子列表时,为什么子列表中的数据没有被删除?是因为没有CASCADE设置,对父对象的操作不能到达子对象吗?或者这是一个bug?我需要一个解释。

z9gpfhce

z9gpfhce1#

在这里,您拥有的是父实体和子实体之间的一对多关系。每个实体都被假定为一个独立存在的组件。让我们以Person和Car之间的一对多关系为例。一个人可以拥有多辆汽车,假设拥有汽车的人去世了,我们将从数据库中删除他的数据,但他拥有的汽车将保留并继续被跟踪,另一方面,当他拥有的汽车被出售给另一个用户或最坏的情况下报废,因为它没有得到适当的维护,对应于特定汽车的记录必须被删除,而用户应该保留在除非你显式地设置级联类型,否则操作不会传播到子实体。如果这不能帮助你理解,请发表评论。

相关问题