我正在尝试将以下SQL转换为Hibernate DetachedCriteria:
SELECT
students0_.courseId AS courseId2_1_,
students0_.studentId AS studentId1_,
student1_.id AS id3_0_,
student1_.href AS href3_0_,
student1_.created AS created3_0_,
student1_.email AS email3_0_,
student1_.enabled AS enabled3_0_,
student1_.firstName AS firstName3_0_,
student1_.lastAccessed AS lastAcce8_3_0_,
student1_.lastName AS lastName3_0_,
student1_.password AS password3_0_,
student1_.role AS role3_0_,
student1_.username AS username3_0_
FROM
course_students students0_
INNER JOIN
users student1_
ON students0_.studentId=student1_.id
WHERE
students0_.courseId IN (
SELECT
this_.id
FROM
courses this_
LEFT OUTER JOIN
assignments assignment2_
ON this_.id=assignment2_.courseId
AND (
assignment2_.availabilityType='Available'
OR (
assignment2_.availabilityType='Range'
AND assignment2_.endDate>= NOW()
AND assignment2_.startDate<= NOW()
)
)
LEFT OUTER JOIN
courses course5_
ON assignment2_.courseId=course5_.id
INNER JOIN
course_students students6_
ON this_.id=students6_.courseId
LEFT OUTER JOIN
users student1_
ON students6_.studentId=student1_.id
WHERE
student1_.id = <id>
AND this_.endDate>= NOW()
AND this_.startDate<= NOW()
)
我有以下代码(注释掉的代码是我尝试的不同迭代):
public Collection<Course> findCoursesByStudent(Student student) {
Calendar currTime = Calendar.getInstance();
// DetachedCriteria subCriteria = DetachedCriteria.forClass(Assignment.class, "assignments");
//subCriteria.createCriteria("assignments", Criteria.FULL_JOIN);
//subCriteria.createAlias("assignments", "assignments");
Disjunction disjunction = Restrictions.disjunction();
disjunction.add(Restrictions.eq("assignments.availabilityType", AvailabilityType.Available));
Conjunction conjunction = Restrictions.conjunction();
conjunction.add(Restrictions.eq("assignments.availabilityType", AvailabilityType.Range));
conjunction.add(Restrictions.ge("assignments.endDate", currTime)).add(Restrictions.le("assignments.startDate", currTime));
disjunction.add(conjunction);
// subCriteria.add(disjunction);
DetachedCriteria criteria = DetachedCriteria.forClass(getPersistentClass());
criteria.createCriteria("students", "student").add(Restrictions.idEq(student.getId()));
criteria.add(Restrictions.ge("endDate", currTime)).add(Restrictions.le("startDate", currTime));
criteria.createAlias("assignments", "assignments", Criteria.LEFT_JOIN);
criteria.setFetchMode("assignments", FetchMode.JOIN).add(disjunction);
//criteria.createCriteria("assignments", "assignments", Criteria.LEFT_JOIN).add(disjunction);
return findByDetachedCriteria(criteria);
}
但是我得到了两个重复的行,而hibernate使用的SQL如下:
select
students0_.courseId as courseId2_1_,
students0_.studentId as studentId1_,
student1_.id as id3_0_,
student1_.href as href3_0_,
student1_.created as created3_0_,
student1_.email as email3_0_,
student1_.enabled as enabled3_0_,
student1_.firstName as firstName3_0_,
student1_.lastAccessed as lastAcce8_3_0_,
student1_.lastName as lastName3_0_,
student1_.password as password3_0_,
student1_.role as role3_0_,
student1_.username as username3_0_
from
course_students students0_
inner join
users student1_
on students0_.studentId=student1_.id
where
students0_.courseId in (
select
this_.id
from
courses this_
left outer join
assignments assignment2_
on this_.id=assignment2_.courseId
left outer join
courses course5_
on assignment2_.courseId=course5_.id
inner join
course_students students6_
on this_.id=students6_.courseId
left outer join
users student1_
on students6_.studentId=student1_.id
where
student1_.id = ?
and this_.endDate>=?
and this_.startDate<=?
and (
assignment2_.availabilityType=?
or (
assignment2_.availabilityType=?
and assignment2_.endDate>=?
and assignment2_.startDate<=?
)
)
)
我已经全神贯注地找到了解决方案。任何帮助将不胜感激。我也试图避免使用HQL。
起亚
答案 0 :(得分:6)
从复杂的hibernate条件查询中获取重复项是一个常见问题,最简单的解决方法是使用专为此问题而生成的结果转换器:
criteria.setResultTransformer( Criteria.DISTINCT_ROOT_ENTITY );
不幸的是,这与滚动和分页无法很好地互动,但它可能适用于您的情况。
更好的解决方案可能是用SubQuery.exists
替换部分限制,以获得子选择检查是否存在匹配而不是检索所有匹配,但这可能很难弄明白。