Java JPA Join打印出许多结果

Java JPA Join打印出许多结果,java,sql-server,eclipse,jpa,Java,Sql Server,Eclipse,Jpa,我有四个表描述数据库: 讲师 注册(使用讲座和学生) 具有自复合主键以来的ID类 public class EnrollmentId implements Serializable { @Id @JoinColumn(name = "lecture_id", referencedColumnName = "id") @ManyToOne private int lecture; @Id @JoinColumn(name = "student_

我有四个表描述数据库:
讲师

注册(使用讲座和学生)

具有自复合主键以来的ID类

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;        
}
讲座(使用讲师)

当我试图构建一个查询时,我得到了很多结果。(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”不起作用。

好吧,因为…上的
不起作用(Hibernate 5将支持它),您需要沿路径加入,或者使用where条件筛选不适合的行。目前,您正在交叉加入所有讲座、讲师、注册和学生,即使它们没有关联

另一个问题是,没有从
讲座
注册
的代码路径,因此您可能希望从
注册
开始。因此,查询可能如下所示(我将跳过常见部分):

最后一条建议:“我有四个表描述数据库”-在这里改变你的想法。您有四个实体描述您的模型,这些实体映射到数据库(但映射可能会改变)。因此,在处理JPA查询时,您需要考虑实体而不是表格,例如,因为没有从
讲座
注册
的路径,除非您的JPA提供商支持通用的
ON
,否则您需要找到一个入口点和一个指向您想要加入的所有内容的路径(例如,有一个从
注册
讲座
的路径,因此您可以从
注册
开始)

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

}
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);
... 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