在下面的Hibernate生成的查询中,student_id
和college_id_fk
字段被选中了两次,为什么是这样,目的是什么?这能修好吗。
2022-02-21 07:12:33.213 TRACE 19824 --- [ main] o.h.type.descriptor.sql.BasicExtractor : extracted value ([student_1_12_0_] : [INTEGER]) - [6]
Hibernate:
select
students0_.college_id_fk as college_3_12_0_,
students0_.student_id as student_1_12_0_,
students0_.student_id as student_1_12_1_,
students0_.college_id_fk as college_3_12_1_,
students0_.student_name as student_2_12_1_
from
student students0_
where
students0_.college_id_fk=?
2022-02-21 07:12:33.214 TRACE 19824 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [INTEGER] - [1]
呼叫代码如下-
collegeRepo.findAll().forEach( c -> System.err.println("college wit students: " + c.getStudents() ) );
以上是spring数据jpa提供的方法,因此它具有从spring数据jpa实现的功能。
我也经历过类似的问题,这表明实体可能有一些错误,比如映射错误或@Id使用错误。所以,我把我的实体关系贴在这里。
实体关系是-学生属于一所大学,一所大学可以有多个学生。学生
这些实体如下。
(小编辑1-遵循肯的建议,我已经评论了College.students实体的急切加载,但“选择两次”问题仍然存在。)编辑1的结尾)
@Entity
public class College {
@Id
@GeneratedValue
private int collegeId;
private String collegeName;
@OneToMany(targetEntity = Student.class, mappedBy = "college") //, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
//as you can see students is loaded eagerly.
private List<Student> students;
和
@Entity
public class Student {
@Id
@GeneratedValue
private int studentId;
private String studentName;
@ManyToOne
@JoinColumn(name = "collegeId_fk")
private College college;
我在搜索引擎上搜索"Hibernate两次选择同一列“。但是没有什么有用的结果。因此,SOF是理解或解决此问题的唯一方法。
应@tgdavies的请求: spring启动版本为2.6.1,hibernate-core版本为5.6.1
发布于 2022-02-22 08:40:19
版本6.0之前的Hibernate依赖于为每一列使用而生成的别名。因此,如果您有多个关联,甚至只是一个与许多关联相反的关联,您将看到重复的列选择,因为在6.0之前的Hibernate基于别名获取值。Hibernate 6.0切换到基于位置的抓取和反重复选择为同一列.
发布于 2022-02-21 04:01:00
您提到的select SQL是由大学学生的急切加载触发的。我简要地跟踪了源代码,并将其归结为OneToManyPersister
,以便在这里生成select子句。我不知道为什么作者会生成select子句,其中包含一些重复的列,而且我认为除非您使用自己修补的hibernate版本,否则您无法改变这种行为。
如果你真的不希望这种情况发生,我的建议是不要对这所大学的学生使用急切的抓取。毕竟,这是个坏主意,因为急切的抓取会带来N+1查询问题。如果你有100所大学,这样的SQL会重复100次来加载这100所大学的学生。
为了避免N+1查询问题和SQL中的重复列,您可以编写一个JPQL查询,以便将该学院与其学生一起获取连接:
@Query("select distinct c from College c left join fetch c.students")
List<College> findAllCollegeWithStudents();
或者,如果您愿意的话,可以使用@EntityGraph
声明性地执行此操作:
@EntityGraph(value = "students")
List<College> findAll();
https://stackoverflow.com/questions/71200665
复制相似问题