Java 通过仅使用FK列而不是相关实体来消除JPA查询中的额外连接';身份证
我与实体的关系如下:Java 通过仅使用FK列而不是相关实体来消除JPA查询中的额外连接';身份证,java,hibernate,jpa,join,criteria-api,Java,Hibernate,Jpa,Join,Criteria Api,我与实体的关系如下: STUDENT many-to-one STUDENT_COURSE one-to-many COURSE @Entity @Table(name = "STUDENT") public course Student { @Id @Column(name = "ID", nullable = false) private Long id; @OneToMany(mappedBy = "student") private Set&l
STUDENT many-to-one STUDENT_COURSE one-to-many COURSE
@Entity
@Table(name = "STUDENT")
public course Student {
@Id
@Column(name = "ID", nullable = false)
private Long id;
@OneToMany(mappedBy = "student")
private Set<StudentCourse> studentCoursees;
// ... other fields and getters and setters
}
@Entity
@Table(name = "COURSE")
public course Course {
@Id
@Column(name = "ID", nullable = false)
private Long id;
@OneToMany(mappedBy = "course")
private Set<StudentCourse> studentCourses;
// ... other fields and getters and setters
}
@Entity
@Table(name = "STUDENT_COURSE")
public course StudentCourse {
@Id
@Column(name = "ID", nullable = false)
private Long id;
@ManyToOne
@JoinColumn(name = "STUDENT_ID", referencedColumnName = "ID")
@NotNull
private Student student;
@ManyToOne
@JoinColumn(name = "COURSE_ID", referencedColumnName = "ID")
@NotNull
private Course course;
// ... other fields and getters and setters
}
基本上,学生和他们的课程之间存在着一种多对多的关系。这种关系由STUDENT\u COURSE
表表示
假设我为学生
、学生课程
和课程
设置了实体,以便:
STUDENT many-to-one STUDENT_COURSE one-to-many COURSE
@Entity
@Table(name = "STUDENT")
public course Student {
@Id
@Column(name = "ID", nullable = false)
private Long id;
@OneToMany(mappedBy = "student")
private Set<StudentCourse> studentCoursees;
// ... other fields and getters and setters
}
@Entity
@Table(name = "COURSE")
public course Course {
@Id
@Column(name = "ID", nullable = false)
private Long id;
@OneToMany(mappedBy = "course")
private Set<StudentCourse> studentCourses;
// ... other fields and getters and setters
}
@Entity
@Table(name = "STUDENT_COURSE")
public course StudentCourse {
@Id
@Column(name = "ID", nullable = false)
private Long id;
@ManyToOne
@JoinColumn(name = "STUDENT_ID", referencedColumnName = "ID")
@NotNull
private Student student;
@ManyToOne
@JoinColumn(name = "COURSE_ID", referencedColumnName = "ID")
@NotNull
private Course course;
// ... other fields and getters and setters
}
请注意,我只加入了STUDENT
和STUDENT\u课程
。通过如上所述设置标准和实体,我似乎被迫加入学生
、学生课程
和课程
,因为我在学生课程
上没有courseId字段:
Join<Person, PersonCourse> personCourse = root.join("personCourses");
Join<PersonCourse, Course> course = personCourse.join("course");
Predicate onlySpecificCourse = builder.equal(course.get("id"), courseId);
然后连接变成:
Join<Person, PersonCourse> personCourse = root.join("personCourses");
Predicate onlySpecificCourse = builder.equal(personCourse.get("courseId"), courseId);
Join personCourse=root.Join(“personCourses”);
仅谓词SpecificCourse=builder.equal(personCourse.get(“courseId”),courseId);
如果我这样做了,有什么我应该注意的地方吗?特别是,在PersonCourse
实体上同时为courseId
和course
设置setter似乎很奇怪。更新 我正在更新我的答案,以便为您提供解决方案,尽管我不喜欢它。:-) 但首先,听起来您希望以面向对象的方式来实现这一点,但您不希望将持久化数据视为对象树,在这种情况下,PersonCourse和Course都是同一个对象树的一部分,但在某些特殊情况下,您希望忘记这一事实。您只能将ORM提升到某一点,之后您将不得不求助于本机SQL 但是,我将在这里提供一个您可能不喜欢的ORM解决方案,因此,它是这样的: 向PersonCourse实体添加一个新属性,并将其映射到联接表中的“课程ID”列。但您必须确保在插入和更新中不使用新属性
@Column(name = "COURSE_ID", insertable = false, updatable = false)
private Long courseId;
现在你可以从方程中去掉课程根,然后用上面的谓词
原始答案 如果STUDENT_CLASS table除了学生和类关系的ID之外没有其他列,那么只需在学生和类实体之间使用@manytomy,而不是@manytomone,并且不需要第三个实体;Hibernate会帮你处理的
如果联接表确实有其他列,例如GRADE或RATING列,则使用如下所述的解决方案: 我很难理解为什么带有额外连接的标准解决方案对您不起作用,您能扩展吗?好问题。添加无用的连接是我想要避免的事情。我查询的ID在第二个表上,所以从技术上讲,连接到第三个表是多余的,可能会对查询的性能产生负面影响。明白了。然而,考虑在IDEXS上加入应该对性能有不可忽视的影响。关于你的解决方案,不幸的是,我不能给你一个答案。没有比你已经解决的问题更多的问题了。至于setter,请记住,JPA将忽略覆盖
courseId
的值。谢谢。联接表中有额外的信息,因此我们不能使用“@manytomy”。我们已经按照您的链接所示绘制了关系图。不过,这并没有回答关于额外连接的原始问题。