我与许多人有“学生”和“阶级”。在它们之间有一个链接表。
如果我想以下列方式检索所有使用HQL的学生,一切都很好:
Query queryObject = getSession().createQuery("from Student");
return queryObject.list();
上面的代码如果有三个学生,我会得到一个三个学生的列表。
但是,如果我使用标准,只要链接表中没有关联,它就可以了。
Criteria crit = getSession().createCriteria(Student.getClass());
return crit.list();
使用第二个代码,仅当链接表为空时才会得到三个结果。但是,当我添加关联时,我得到6个结果。查看日志,Hibernate会生成多个选择。怎么可能?
有人可以解释为什么会这样吗?如何修复标准以便仅返回三个记录?
修改
在Student类中,我以这种方式映射:
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(
name="room_student_rel"
, joinColumns={
@JoinColumn(name="id_student")
}
, inverseJoinColumns={
@JoinColumn(name="id_room")
}
)
private List<Room> rooms;
在房间(班级)中,我以这种方式进行了映射:
@OneToMany(fetch=FetchType.EAGER, mappedBy="room")
@Fetch(FetchMode.SELECT)
private List<RoomStudent> roomStudents;
答案 0 :(得分:3)
要扩展我之前的评论,当FetchType设置为EAGER时,Hibernate将尝试使用外部联接。
见以下2.2.5.5:
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/
有关这方面的含义,请参阅此处:
Hibernate Criteria returns children multiple times with FetchType.EAGER
现在您还可以指定FetchMode(在您的条件.setFetchMode("assocFiled",FetchMode.LAZY)
上)将其设置为JOIN以外的其他内容,或者您可以使用criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
之类的内容来过滤重复项。
理想情况下,您应该在实体映射上避免使用EAGER,并且需要急切提取的地方在实体加载时使用一些提示或通过FetchProfile显式启用它,然后在需要时处理重复项。