【问题标题】:JPA Join Prints to many ResultsJPA 加入打印到许多结果
【发布时间】:2020-02-19 10:57:14
【问题描述】:

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

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

自复合主键以来的 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;        
}

讲座(使用讲师)

@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”不起作用。

【问题讨论】:

    标签: java sql-server eclipse jpa


    【解决方案1】:

    好吧,由于ON ... 不起作用(Hibernate 5 会支持它),您需要沿着路径加入或使用 where 条件来过滤不适合的行。目前,您正在交叉加入所有讲座、讲师、注册和学生,即使他们不相关。

    另一个问题是没有从LectureEnrollment 的代码路径,因此您可能希望从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 查询时,您需要考虑实体而不是表,例如因为没有从LectureEnrollment 的路径,并且除非您的JPA 提供程序支持通用ON,否则您需要找到一个入口点和您想要加入的所有内容的路径(例如,有一条从Enrollment 到@987654330 的路径@ 所以你从Enrollment开始)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-06
      • 2017-11-27
      • 1970-01-01
      • 2015-02-20
      • 2018-08-12
      • 2016-02-29
      • 2021-08-11
      • 2017-10-01
      相关资源
      最近更新 更多