【问题标题】:How to solve the targeting an unmapped class error from hibernate?如何解决从休眠中定位未映射的类错误?
【发布时间】:2019-10-10 10:15:21
【问题描述】:

我正在尝试映射 2 个实体(课程和学生),我有 2 个 Java 类和 2 个 MySQL 表,具有ManyToMany 关系。我创建了联结表和 java 类 Enrollment(因为我想要额外的信息,例如学生注册课程的日期)。

我正在尝试在 MySQL 的这个 Enrollments 表中使用休眠功能插入数据,但我不断收到错误消息。这是我的 POJO 课程:

课程类别:

@Entity
@Table(name = "course")
public class Course {


private int id;

@Column(name = "chapter_id")
private int chapterId;;

@Column(name = "name")
private String title;   

@Column(name = "teacher_user_id")
private int teacherId;

 @OneToMany(targetEntity=Enrolment.class, mappedBy="course", fetch=FetchType.LAZY)
// @JoinTable(name = "enrolment",
         //   joinColumns = @JoinColumn(name = "course_id"),
         //   inverseJoinColumns = @JoinColumn(name = "student_user_id"))
private List<Enrolment> enrolments = new ArrayList<Enrolment>();

public Course(){}

public Course(int id, int chapterId, String title, int teacherId) {
    super();
    this.id = id;
    this.chapterId = chapterId;
    this.title = title;
    this.teacherId = teacherId;
}


@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
    return id;
}


public void setId(int id) {
    this.id = id;
}


public int getChapterId() {
    return chapterId;
}


public void setChapterId(int chapterId) {
    this.chapterId = chapterId;
}


public String getTitle() {
    return title;
}


public void setTitle(String title) {
    this.title = title;
}


public int getTeacherId() {
    return teacherId;
}


public void setTeacherId(int teacherId) {
    this.teacherId = teacherId;
}

@OneToMany(mappedBy = "course")
public List<Enrolment> getEnrolments() {
    return enrolments;
}

public void setEnrolments(List<Enrolment> courses) {
    this.enrolments = courses;
}

public void addEnrolment(Enrolment enrolment) {
    this.enrolments.add(enrolment);
}
}

Student 类(这个类继承自 User 父类,下面我也会附上 User Class。在数据库中也有不同的表:User,然后 Student 和 Teacher 继承了 User 父实体):

@Entity
@Table(name = "student")
@PrimaryKeyJoinColumn(name = "user_id")
@OnDelete(action = OnDeleteAction.CASCADE)
public class Student extends User  {

private int grade;


private List<Enrolment> enrolments = new ArrayList<Enrolment>();

public Student(){} 

public Student(String fname, String lname, String email, String password, String address, String phone,
        int userType, int grade, boolean isAdmin) 
{
    super(fname, lname, email, password, address, phone, userType, isAdmin);

    this.grade=grade;

}

public int getGrade() {
    return grade;
}

public void setGrade(int grade) {
    this.grade = grade;
}


public void setEnrolments(List<Enrolment> courses) {
    this.enrolments = courses;
}

@OneToMany(mappedBy = "student")
public List<Enrolment> getEnrolments() {
    return enrolments;
}

public void addCourse(Enrolment course) {
    this.enrolments.add(course);
}

public void addEnrolment(Enrolment enrolment) {
    this.enrolments.add(enrolment);
}

}

用户类别:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "user")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String firstname;
private String lastname;
private String email;
private String password;
private String address;
private String phone;

@Column(name = "user_type_id")
private int userType;

@Column(name = "is_admin")
private boolean isAdmin;


public User(String fname, String lname, String email, String password, String address, String phone,
        int userType, boolean isAdmin) {
    //super();

    this.firstname = fname;
    this.lastname = lname;
    this.email = email;
    this.password = password;
    this.address = address;
    this.phone = phone;
    this.userType = userType;
    this.isAdmin = isAdmin;
}

public User() {}
//getters & setters

最后是 Enrollment 类:

@Entity
@Table(name = "enrolment")
public class Enrolment {


private int id;
private Student user;
private Course course;

@Column(name = "enrolment_date")
private Date enrolmentDate;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}


@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "student_user_id")
public User getUser() {
    return user;
}

public void setUser(Student user) {
    this.user = user;
}

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "course_id")
public Course getCourse() {
    return course;
}

public void setCourse(Course course) {
    this.course = course;
}

public Date getEnrolmentDate() {
    return enrolmentDate;
}

public void setEnrolmentDate(Date enrolmentDate) {
    this.enrolmentDate = enrolmentDate;
}

所以我正在尝试从数据库中读取课程和学生并将信息插入此 Enrollment 表中,但由于尝试读取课程而出现错误。这是DAO方法:

 @SuppressWarnings("deprecation")
@Transactional
public List<Course> getCoursesOfChapter(int chapterId) {


    Configuration con = new Configuration().configure("hibernate.cfg.xml").addAnnotatedClass(Course.class);
    SessionFactory sf = con.buildSessionFactory();
    Session session = sf.openSession();
    Transaction tx = session.beginTransaction();


    Query query = session.createQuery("from Course where chapter_id = :chapterId");
      query.setParameter("chapterId",chapterId);

     // List list = query.list();

        tx.commit();
      return (List<Course>) query.list();

它在会话工厂构建时抛出错误:

Exception in thread "main" org.hibernate.AnnotationException: Use of @OneToMany or @ManyToMany targeting an unmapped class: models.Course.enrolments[models.Enrolment]
at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1255)
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:808)
at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:733)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:54)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1696)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1664)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:287)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:84)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:474)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:85)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:689)
at dao.CourseDAO.getCourse(CourseDAO.java:52)
at webapp.Main.main(Main.java:132)

最后,这是我的电话:

CourseDAO cdao = new CourseDAO();

Course course = cdao.getCourse(1);

我尝试过使用注释,将它们设为多对多而不是多对一。我试图映射用户类而不是学生,但仍然没有工作。我试图在没有 Enrollment 连接类的情况下制作它,并且在没有实际类的情况下生成它,但仍然没有工作(因为我不得不一个接一个地使用 2 个 session.save() 方法,这也给了一些我无法解决的错误)。可能这是我在这里遗漏的一件小事,但我无法弄清楚,抱歉代码太长,但我真的需要快速解决它。如果你读到这里,我真的很感谢你!

所以我的问题是:我是否从这些映射和注释中遗漏了一些东西,或者我应该改变我的类的结构?

【问题讨论】:

    标签: java hibernate mapping


    【解决方案1】:

    将问题归结为最低限度总是有帮助的。以下是您的学生、课程和注册课程的更简单版本,可以轻松进行单元测试。课程和学生之间的多对多关联从 Enrollment 分为两个多对一关联。请注意,关联是双向的,并且 many 端由 one 端映射。学生将持久性操作级联到 Enrollment,这反映了学校的正常工作方式:学生注册课程,而不是相反。

    Course.java

    @Entity
    public class Course {
    
        @Id
        @GeneratedValue
        private Long id;
    
        private String title;
    
        @OneToMany(mappedBy = "course")
        private List<Enrollment> enrollments;
    
        Course() {
        }
    
        Course(String title) {
            this.title = title;
            this.enrollments = new ArrayList<>();
        }
    
        void add(Enrollment enrollment) {
            enrollments.add(enrollment);
        }
    
        Long getId() {
            return id;
        }
    
        List<Enrollment> getEnrollments() {
            return enrollments;
        }
    }
    

    Student.java

    @Entity
    public class Student {
    
        @Id
        @GeneratedValue
        private Long id;
    
        private String name;
    
        @OneToMany(mappedBy = "student", cascade = ALL, orphanRemoval = true)
        private List<Enrollment> enrollments;
    
        Student() {
        }
    
        Student(String name) {
            this.name = name;
            this.enrollments = new ArrayList<>();
        }
    
        void enroll(Course course) {
            enrollments.add(new Enrollment(course, this));
        }
    }
    

    Enrollment.java

    @Entity
    public class Enrollment {
    
        @Id
        @GeneratedValue
        private Long id;
    
        @ManyToOne
        private Course course;
    
        @ManyToOne
        private Student student;
    
        Enrollment() {
        }
    
        Enrollment(Course course, Student student) {
            this.course = course;
            this.student = student;
            course.add(this);
        }
    }
    

    下面的测试用例检查实体是否正确映射和关联。您可以使用 Spring Boot 运行它。

    SchoolTest.java

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @Transactional
    public class SchoolTest {
    
        @Autowired
        private CourseRepository courseRepository;
        @Autowired
        private StudentRepository studentRepository;
    
        @Test
        public void run() {
            Course course = courseRepository.save(new Course("cs_101"));
    
            int studentCount = 3;
            for (int i = 1; i <= studentCount; i++) {
                Student student = new Student("student_" + i);
                student.enroll(course);
                studentRepository.save(student);
            }
    
            // push changes to the database and clear the existing entities 
            // to make the subsequent operations load from the database
            entityManager.flush();
            entityManager.clear();
    
            Optional<Course> savedCourse = courseRepository.findById(course.getId());
            assertTrue(savedCourse.isPresent());
            assertEquals(studentCount, savedCourse.get().getEnrollments().size());
        }
    }
    

    【讨论】:

      【解决方案2】:

      正如警告所说,您的 Enrollment 未在 Hibernate 中注册。如果你真的不需要它。请使用瞬态注释。阅读更多here

      【讨论】:

        猜你喜欢
        • 2011-05-13
        • 2013-02-09
        • 1970-01-01
        • 1970-01-01
        • 2017-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-24
        相关资源
        最近更新 更多