我有Course.java类:
package com.ashwin.jpa.hiberante.jpaapp.entity;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name="course")
public class Course {
@Id
@GeneratedValue
private Long id;
@Column(name="name",nullable = false)
private String name;
@UpdateTimestamp
private LocalDateTime localDateTime;
@CreationTimestamp
private LocalDateTime createdDate;
//one to many
@OneToMany(mappedBy = "course",fetch = FetchType.EAGER)
private List<Review> reviewList=new ArrayList<>();
//many to many
@ManyToMany(mappedBy = "courses")
private List<Student> students=new ArrayList<>();
public Course(String name) {
this.name = name;
}
public Course(){
this.name=name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Course{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public List<Review> getReviewList() {
return reviewList;
}
public void setReview(Review review) {
this.reviewList.add(review);
}
public void removeReview(Review review) {
this.reviewList.remove(review);
}
public List<Student> getStudents() {
return students;
}
public void setStudent(Student student) {
this.students.add(student);
}
}
我有Student.java类
package com.ashwin.jpa.hiberante.jpaapp.entity;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Entity
public class Student {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String name;
//a student can have one passport
@OneToOne(fetch = FetchType.LAZY)
private Passport passport;
//many to many mapping
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name="STUDENT_COURSE",joinColumns = @JoinColumn(name="STUDENT_ID"),
inverseJoinColumns = @JoinColumn(name="COURSE_ID"))
private List<Course> courses=new ArrayList<>();
public Student(String name) {
this.name = name;
}
public Student(){
this.name=name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public Passport getPassport() {
return passport;
}
public void setPassport(Passport passport) {
this.passport = passport;
}
public List<Course> getCourses() {
return courses;
}
public void setCourse(Course course) {
this.courses.add(course);
}
}
这两个类通过“多对多”注释进行映射。实际上,起初我在Student.java类中的代码是:
//many to many mapping
@ManyToMany
@JoinTable(name = "STUDENT_COURSE", joinColumns = @JoinColumn(name = "STUDENT_ID")
private List<Course> courses=new ArrayList<>();
在此阶段,代码已成功编译,我在StudentRepositoryTest.java中使用测试用例获得了结果,
package com.ashwin.jpa.hiberante.jpaapp;
import com.ashwin.jpa.hiberante.jpaapp.entity.Course;
import com.ashwin.jpa.hiberante.jpaapp.entity.Passport;
import com.ashwin.jpa.hiberante.jpaapp.entity.Student;
import com.ashwin.jpa.hiberante.jpaapp.repository.CourseRepository;
import com.ashwin.jpa.hiberante.jpaapp.repository.StudentRepository;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
@RunWith(SpringRunner.class)
@SpringBootTest
public class StudentRepositoryTest {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private StudentRepository studentRepository;
@Autowired
private EntityManager entityManager;
@Test
@Transactional
public void retrieveStudentAndCourses() {
//many to many mapping
Student student = entityManager.find(Student.class, 7 L);
logger.info("student is ->{}", student);
logger.info("student course is ->{}", student.getCourses());
}
}
输出为:
Hibernate: select student0_.id as id1_3_0_, student0_.name as name2_3_0_, student0_.passport_id as passport3_3_0_ from student student0_ where student0_.id=?
2019-08-01 20:58:38.410 TRACE 18608 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [7]
2019-08-01 20:58:38.464 TRACE 18608 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([name2_3_0_] : [VARCHAR]) - [Mike]
2019-08-01 20:58:38.466 TRACE 18608 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([passport3_3_0_] : [BIGINT]) - [6]
2019-08-01 20:58:38.507 TRACE 18608 --- [ main] org.hibernate.type.CollectionType : Created collection wrapper: [com.ashwin.jpa.hiberante.jpaapp.entity.Student.courses#7]
2019-08-01 20:58:38.560 INFO 18608 --- [ main] c.a.j.h.jpaapp.StudentRepositoryTest : student is ->Student{id=7, name='Mike'}
Hibernate: select courses0_.student_id as student_1_4_0_, courses0_.course_id as course_i2_4_0_, course1_.id as id1_0_1_, course1_.created_date as created_2_0_1_, course1_.local_date_time as local_da3_0_1_, course1_.name as name4_0_1_ from student_course courses0_ inner join course course1_ on courses0_.course_id=course1_.id where courses0_.student_id=?
Hibernate: select reviewlist0_.course_id as course_i4_2_0_, reviewlist0_.id as id1_2_0_, reviewlist0_.id as id1_2_1_, reviewlist0_.course_id as course_i4_2_1_, reviewlist0_.description as descript2_2_1_, reviewlist0_.rating as rating3_2_1_ from review reviewlist0_ where reviewlist0_.course_id=?
Hibernate: select reviewlist0_.course_id as course_i4_2_0_, reviewlist0_.id as id1_2_0_, reviewlist0_.id as id1_2_1_, reviewlist0_.course_id as course_i4_2_1_, reviewlist0_.description as descript2_2_1_, reviewlis
2019-08-01 20:58:38.561 INFO 18608 --- [ main] c.a.j.h.jpaapp.StudentRepositoryTest : student course is ->[Course{id=10001, name='JPA in 50steps'}, Course{id=10002, name='Spring in 50steps'}]
但是当我添加(fetch = FetchType.EAGER)时,如下所示:
//many to many mapping
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name="STUDENT_COURSE",joinColumns = @JoinColumn(name="STUDENT_ID"),
inverseJoinColumns = @JoinColumn(name="COURSE_ID"))
private List<Course> courses=new ArrayList<>();
我得到的错误是:
org.springframework.beans.factory.BeanCreationException:错误 在类路径中创建名称为“ entityManagerFactory”的bean 资源 [org / springframework / boot / autoconfigure / orm / jpa / HibernateJpaConfiguration.class]: 调用init方法失败;嵌套异常为 javax.persistence.PersistenceException:[每
原因:org.hibernate.loader.MultipleBagFetchException:无法 同时获取多个袋子: [com.ashwin.jpa.hiberante.jpaapp.entity.Student.courses, com.ashwin.jpa.hiberante.jpaapp.entity.Course.reviewList]