Как решить проблему нацеливания на несопоставленную ошибку класса из спящего режима? - PullRequest
0 голосов
/ 23 мая 2019

Я пытаюсь отобразить 2 объекта (курс и ученик), у меня есть 2 класса Java и 2 таблицы MySQL, имеющие отношение ManyToMany. Я создал соединительную таблицу и зачисление в java-класс (так как мне нужна дополнительная информация, такая как дата зачисления студента на курс).

Я пытаюсь вставить данные, используя режим гибернации, в эту таблицу регистрации в MySQL, но продолжаю получать ошибки. Вот мои классы 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);
}
}

Класс ученика (этот класс унаследован от родительского класса пользователя, ниже я также прикреплю класс пользователя. В базе данных также есть разные таблицы: пользователь, а затем ученик и учитель, которые наследуют родительскую сущность пользователя):

@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

И, наконец, это класс Зачисления:

@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;
}

Итак, я пытаюсь прочитать курс и учащегося из базы данных и вставить информацию в эту таблицу зачисления, но это дает ошибки, так как я пытаюсь прочитать курс. Вот метод 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);

Я попробовал поиграть с аннотациями, сделать их ManyToMany вместо ManyToOne. Я пытался сопоставить класс User вместо Student, но все равно не работал. Я попытался сделать это без класса соединения Enrollment и просто сгенерировать его, не имея фактического класса для него, но все еще не работал (так как мне приходилось работать с двумя методами session.save () один за другим, что также давало некоторые ошибка, которую я не мог решить). Возможно, это небольшая вещь, которую я здесь упускаю, но я просто не могу понять это, извините за слишком длинный код, но мне действительно нужно решить это быстро. Если вы прочитали здесь, я очень благодарен вам!

Итак, мой вопрос: я что-то упускаю из этих отображений и аннотаций или мне следует изменить структуру моих классов?

Ответы [ 2 ]

1 голос
/ 23 мая 2019

Это всегда помогает свести проблемы к минимуму.Вот более простые версии вашего студента, курса и зачисления классов, которые могут быть легко проверены модулем.Ассоциация «многие ко многим» между курсом и студентом разделена на две ассоциации «многие к одному» из зачисления.Обратите внимание, что ассоциации являются двунаправленными и что сторона 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());
    }
}
0 голосов
/ 23 мая 2019

Как сказано в предупреждении, ваша регистрация не зарегистрирована в Hibernate.Если тебе это действительно не нужно.Пожалуйста, используйте переходную аннотацию.читать дальше здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...