Hibernate使用DetachedCriteria进行LEFT OUTER JOIN

时间:2011-01-13 23:51:28

标签: hibernate outer-join detachedcriteria

我正在尝试将以下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。

起亚

1 个答案:

答案 0 :(得分:6)

从复杂的hibernate条件查询中获取重复项是一个常见问题,最简单的解决方法是使用专为此问题而生成的结果转换器:

criteria.setResultTransformer( Criteria.DISTINCT_ROOT_ENTITY );

不幸的是,这与滚动和分页无法很好地互动,但它可能适用于您的情况。

更好的解决方案可能是用SubQuery.exists替换部分限制,以获得子选择检查是否存在匹配而不是检索所有匹配,但这可能很难弄明白。