了解 Spring JPA 映射

Understanding Spring JPA mapping

我正在努力了解 Spring 数据 JPA 映射。我写了一个简单的应用程序,它有一个 PersonChild 对象。每个 Person 可以有很多 Child 关系,每个 Child 可以有一个 Person

import com.example.demo.children.Child;
import lombok.Data;

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

@Entity
@Data
public class Person {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    private String firstName;
    private String lastName;

    //Only used for Spring data JPA so use protected
    protected Person() {}

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @OneToMany(
            mappedBy = "person",
            cascade = CascadeType.ALL,
            orphanRemoval = true,
            fetch = FetchType.EAGER
    )
    private List<Child> children = new ArrayList<>();

    @Override
    public String toString() {
        return String.format(
                "Person[id=%d, firstName='%s', lastName='%s', children='%s']",
                id, firstName, lastName, children);
    }
}
import com.example.demo.person.Person;
import lombok.Data;

import javax.persistence.*;

@Entity
@Data
public class Child {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;
    private String firstName;
    private String lastName;

    protected Child() {}

    public Child(String first, String last) {
        this.firstName = first;
        this.lastName = last;
    }

    @ManyToOne(fetch = FetchType.EAGER)
    private Person person;

    @Override
    public String toString() {
        return String.format(
                "Child[id=%d, firstName='%s', lastName='%s', parent='%s']",
                id, firstName, lastName, person);
    }
}

主要 class,

import java.util.ArrayList;
import java.util.List;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    public CommandLineRunner demo(PersonRepository repository, ChildRepository cRepo) {
    return (args) -> {
        // save a few people
        Person dad = new Person("John", "Jones");
        Child c1 = new Child("Emily", "Jones");
        Child c2 = new Child("Thomas", "Jones");
        List<Child> kids = new ArrayList<>();
        kids.add(c1);
        kids.add(c2);
        dad.setChildren(kids);
        repository.save(dad);

        Person p = repository.findById(1);
        System.out.println(p);

    };
}

}

当 运行 以上时,我得到 Person[id=1, firstName='John', lastName='Jones', children='[]'] 和一个空的 Child 对象列表。如果我添加

        List<Child> children = cRepo.findAll();
        p.setChildren(children);

在打印出 Person 对象之前 System.out.println(p); 然后我得到 Person[id=1, firstName='John', lastName='Jones', children='[Child[id=2, firstName='Emily', lastName='Jones', parent='null'], Child[id=3, firstName='Thomas', lastName='Jones', parent='null']]']

因此 Child 没有与 Person 对象一起保存在数据库中。

我无法弄清楚我做错了什么才能让它正常工作。

虽然 save 成功地从 parent 级联到其关联的 children (CascadeType.ALL),但 child objects 做没有在保存时设置他们的“爸爸”(person)。

并且由于它们是关联的拥有方,它们的关系不会持久化,因此在下次检索时留下一个空的 children 列表parent 人。

要使您的代码正常工作,只需添加适当的双向关联同步,例如通过在 children.

上调用 c1.setPerson(dad)

https://vladmihalcea.com/jpa-hibernate-synchronize-bidirectional-entity-associations/