JPA объединяет печать многих результатов - PullRequest
0 голосов
/ 23 октября 2019

У меня есть четыре таблицы, описывающие базу данных:
Лектор

@Entity
@Table(name = "LECTURER")

public class Lecturer
{
    private static final long            serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)  
    private int id;

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

    @Column(name = "NOBEL_PRICE_YEAR")
    private int nobel_price_year;
}```

Зачисление (с использованием лекций и учеников)

@Entity
@IdClass(EnrollmentId.class)
@Data
public class Enrollment
{
   @Id
   @JoinColumn(name = "lecture_id", referencedColumnName = "id")
   @ManyToOne
   private Lecture lecture;


   @Id
   @JoinColumn(name = "student_id", referencedColumnName = "id")
   @ManyToOne
   private Student student;

   @Id
   private int year;

   @Column(nullable = false, columnDefinition = "TINYINT(1)")
   private boolean exam_taken;
   @Column(nullable = false, columnDefinition = "TINYINT(1)")
   private boolean exam_passed;
}

С идентификатором класса с составного первичного ключа

public class EnrollmentId implements Serializable 
{

    @Id
    @JoinColumn(name = "lecture_id", referencedColumnName = "id")
    @ManyToOne
    private int lecture;

    @Id
    @JoinColumn(name = "student_id", referencedColumnName = "id")
    @OneToOne
    private int student;

    private int year;
}

Студент

@Entity
@Table(name="STUDENT")
@Data
@NamedQuery(name = "Student.findAll", query = "SELECT s FROM Student s")
public class Student
{
    private static final long           serialVersionUID = 1L;

    @Id
    @Column(name="ID", nullable=false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)    
    private int id;

    @Column(name="FIRSTNAME", nullable=false)
    private String firstname;

    @Column(name="LASTNAME", nullable=false)
    private String lastname;

    @Column(name="YEAR_OF_BIRTH")
    private int yearOfBirth;

    @Column(name="GENDER")
    @Enumerated(EnumType.STRING)
    private Gender gender;        
}

Лекция (с помощью лектора)

@Entity
@Table(name="LECTURE")
public class Lecture
{
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)  
    private int id;

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

    @JoinColumn(name="LECTURER_ID", referencedColumnName = "id")
    @ManyToOne
    private Lecturer lecturer;

    @Column(name = "ROOM")
    @Enumerated(EnumType.STRING)
    private Room room;

    @Column(name = "DAY_OF_WEEK")
    private DayOfWeek dow;

    @JoinColumn(name = "PREREQUISITE_ID", referencedColumnName = "id")
    @ManyToOne
    private Lecture prerequisite;             

}

Когда я пытаюсь построить запрос, я получаю много результатов. (SQL Server печатает 129 по одному и тому же запросу, JPA 90k +)

Запрос:

Query q = em.createQuery("SELECT"
            + "  l.title, l.dow, l.room "
            + ", t.name, CASE WHEN (t.nobel_price_year != NULL) THEN 'YES' ELSE 'No' END"
            + ", e.year, e.exam_taken, e.exam_passed "
            + ", CONCAT(s.lastname,', ', s.firstname) AS student "
            + "FROM Lecture l "
            + "JOIN Lecturer t "
            + "JOIN Enrollment e "
            + "JOIN Student s "
            + "ORDER BY l.id", EmpireDBExample.class);

Код создается вручную, поскольку соединение с SQL Server не применимо к Eclipse (насколько язнать / выяснить).

Есть ли ошибка в сопоставлениях?
Нужно ли добавлять условия соединения? Если так, как я могу достичь этого? «ON a.id = b.id» не работает.

1 Ответ

1 голос
/ 23 октября 2019

Ну, так как ON ... не работает (Hibernate 5 поддержит его), вам нужно присоединиться по пути или использовать там, где условия для фильтрации строк, которые не подходят. В настоящее время вы объединяете все лекции, лекторы, зачисления и студентов, даже если они не связаны между собой.

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

... FROM Enrollment e  
      JOIN e.lecture l  //join the lecture for the enrollment
      JOIN l.lecturer t //join the lecturer for the lecture
      JOIN e.student s  //join the enrolled student

Одна последняя рекомендация: «У меня есть четыре таблицы, описывающие базу данных» - измените ваше мышление здесь. У вас есть четыре сущности , описывающие вашу модель, и они сопоставлены с базой данных (хотя это сопоставление может измениться). Таким образом, при работе с запросами JPA вы должны думать с точки зрения сущностей, а не таблиц, например, поскольку нет пути от Lecture до Enrollment, и если ваш провайдер JPA не поддерживает универсальный ON, вам нужно найти точку входа ипуть ко всему, к чему вы хотите присоединиться (например, есть путь от Enrollment до Lecture, поэтому вы начинаете с Enrollment).

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