![](/img/trans.png)
[英]org.hibernate.PropertyAccessException while persisting ManyToMany relationship
[英]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
和@ManyToMany
的Course.class
上的@ManyToMany
。
這將正確地意味着當您從Course.class
一側檢查時,許多課程可以同時與許多學生相關!
這是因為 ManyToMany 關系中的默認FetchType設置為LAZY 。 如果你想要你的課程,你需要實現一個查詢來獲取課程或將 FetchType 設置為 EAGER(不好的做法)。
試試實體圖。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.