簡體   English   中英

多對多關系不存在

[英]ManyToMany relationship not persisting

我是 Spring 數據和 JPA 世界的新手。

我有以下實體:

學生:

@Entity
@Table(name = "STUDENT")
public class Student {
@Id
@GeneratedValue
private Integer studentId;

@Column
private boolean fullTime;

@Column
private Integer age;

@Embedded
private Person attendee;

@ManyToMany(mappedBy = "students", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Course> courses = new ArrayList<>();

public Student(Person attendee, boolean fullTime, Integer age) {
    this.attendee = attendee;
    this.fullTime = fullTime;
    this.age = age;
    courses = new ArrayList<>();
}

//getter and setters here
}

課程:

@Entity
@Table(name = "COURSE")
public class Course {
@Id
@GeneratedValue
private Integer id;

@Column
private String name;

@ManyToOne
@JoinColumn
private Department department;

@ManyToMany
@JoinTable
List<Student> students;

public Course(String name, Department department) {
    this.name = name;
    this.department = department;
}

//getters and setters
}

部門:

@Entity
@Table(name = "Department")
public class Department {
@Id
@GeneratedValue
private Integer id;

@Column
private String name;

@OneToMany(mappedBy = "department", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Course> courses = new ArrayList<>();

public Department(String name) {
    this.name = name;
}

//getters and setters
}

我有以下測試用例探索彈簧數據的基本功能:

@RunWith(SpringRunner.class)
@SpringBootTest
public class CrudRepositoryDemo {

Department department;
Course course;
Course course1;

@Autowired
StudentRepository studentRepository;

@Autowired
CourseRepository courseRepository;

@Autowired
DepartmentRepository departmentRepository;

/**
 * Exercise CrudRepository methods.
 */
@Test
public void simpleStudentCrudExample() {
    boolean fullTime = true;
    studentRepository.save(new Student(new Person("jane", "doe"), fullTime, 20));
    studentRepository.save(new Student(new Person("john", "doe"), fullTime, 22));
    studentRepository.save(new Student(new Person("mike", "smith"), fullTime, 18));
    studentRepository.save(new Student(new Person("ally", "kim"), !fullTime, 19));

    createDepartment();
    createCourse();

    System.out.println("\n*************Original Students*************");
    studentRepository.findAll().forEach(System.out::println);

    System.out.println("\n*************Printing courses*************");
    List<Course> all = courseRepository.findAll();
    all.forEach(System.out::println);

    //age up the students and add course
    studentRepository.findAll().forEach(student -> {
        student.setAge(student.getAge() + 1);
        student.getCourses().addAll(all);
        Student save = studentRepository.save(student);
        System.out.println(save);
    });

    System.out.println("\n*************Students a year older and course added*************");
    for (Student student : studentRepository.findAll()) {
        System.out.println("Name of student = " + student.getAttendee().getFirstName() + ". Course = " + student.getCourses());
    }

    studentRepository.deleteAll();
}

private void createCourse() {
    course = new Course("Algorithm", department);
    course1 = new Course("Databases", department);

    courseRepository.save(course);
    courseRepository.save(course1);
}

private void createDepartment() {
    department = new Department("CompSci");
    departmentRepository.save(department);


    System.out.println("\n*************The following department has been saved*************");
    departmentRepository.findAll().forEach(System.out::println);
}
}

現在,當我運行上述測試時,它會編譯並執行,但由於某種原因,只有最后一個學生有一個基於 output 的課程與之關聯。 我可以從日志中看到學生確實保存了課程,但是當我查看所有學生時,只有一個學生有與之關聯的課程,而其他學生沒有課程。

我懷疑這是因為我使用了從學生到課程的@OneToMany 。但對我來說,它是一個單向的 OneToMany(在這種情況下)是有意義的,因為一個學生可以有多個課程。 我不關心與學生有任何關系的課程,因此它是單向的。

所以我的總體問題是為什么其他學生沒有將課程保存給他們? 為什么只有一個學生?

編輯 = 這是使用多對多后的 output(我也更新了學生和課程實體。我更新了學生的 toString 方法,因此更容易查看日志中發生的情況。):

*************The following department has been saved*************
2021-12-11 20:56:25.811  INFO 11980 --- [           main] o.h.h.i.QueryTranslatorFactoryInitiator  : HHH000397: Using ASTQueryTranslatorFactory
Department{id=5, name='CompSci', courses=[]}

*************Original Students*************
Student{studentId=1,  firstName='jane', lastname='doe' , fullTime=true, age=20 , course=}

Student{studentId=2,  firstName='john', lastname='doe' , fullTime=true, age=22 , course=}

Student{studentId=3,  firstName='mike', lastname='smith' , fullTime=true, age=18 , course=}

Student{studentId=4,  firstName='ally', lastname='kim' , fullTime=false, age=19 , course=}


*************Printing courses*************
Course{id=6, name='Algorithm', department=CompSci}
Course{id=7, name='Databases', department=CompSci}
Student{studentId=1,  firstName='jane', lastname='doe' , fullTime=true, age=21 , course=AlgorithmDatabases}

Student{studentId=2,  firstName='john', lastname='doe' , fullTime=true, age=23 , course=AlgorithmDatabases}

Student{studentId=3,  firstName='mike', lastname='smith' , fullTime=true, age=19 , course=AlgorithmDatabases}

Student{studentId=4,  firstName='ally', lastname='kim' , fullTime=false, age=20 , course=AlgorithmDatabases}


*************Students a year older and course added*************
Student{studentId=1,  firstName='jane', lastname='doe' , fullTime=true, age=21 , course=}

Student{studentId=2,  firstName='john', lastname='doe' , fullTime=true, age=23 , course=}

Student{studentId=3,  firstName='mike', lastname='smith' , fullTime=true, age=19 , course=}

Student{studentId=4,  firstName='ally', lastname='kim' , fullTime=false, age=20 , course=}

您需要了解@OneToMany含義以及您在案例中濫用它的原因。

@Entity
@Table(name = "STUDENT")
public class Student {

....

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn//(name = "id")
private List<Course> courses = new ArrayList<>();

...

@OneToMany表示 1 名學生可以參考許多課程。 到這里為止,這對你有好處。

Bot 你被迫在另一邊(Course.class)使用@ManyToOne ,這意味着許多課程只與一個學生相關

您的結構需要 @ManyToMany 的Student.class@ManyToManyCourse.class上的@ManyToMany

這將正確地意味着當您從Course.class一側檢查時,許多課程可以同時與許多學生相關!

這是因為 ManyToMany 關系中的默認FetchType設置為LAZY 如果你想要你的課程,你需要實現一個查詢來獲取課程或將 FetchType 設置為 EAGER(不好的做法)。

試試實體圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM