Hibernate LEFT OUTER JOIN 与 DetachedCriteria

发布于 2024-10-11 19:16:33 字数 4884 浏览 2 评论 0原文

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

起亚

I am trying to transform the following SQL into 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()

      )

I have the following code (commented out code are different iterations that I have tried):

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);
}

However I get two duplicate rows as a result of this and the SQL that hibernate uses is as following:

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<=?
                )
            )
    )

I have looked all over for a solution. Any help will be appreciated. I am also trying to avoid using HQL.

Kia

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

许一世地老天荒 2024-10-18 19:16:33

从复杂的休眠条件查询中获取重复项是一个常见问题,最简单的解决方法是使用专门针对此问题制作的结果转换器:

criteria.setResultTransformer( Criteria.DISTINCT_ROOT_ENTITY );

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

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

Getting duplicates from a complex hibernate criteria query is a common problem, and the easiest fix is to use a result transformer made just for this issue:

criteria.setResultTransformer( Criteria.DISTINCT_ROOT_ENTITY );

Unfortunately, this doesn't interact well with scrolling and paging, but it may work in your case.

A better solution might be to replace some part of your restrictions with SubQuery.exists to get a sub-selection checking existence of matches instead of retrieval of all matches, but this can be painful to figure out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文