2011-01-13 113 views
3

我想变换下面的SQL进入休眠的DetachedCriteria:休眠LEFT OUTER JOIN用的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); 
} 

不过,我得到两个重复的行为这样的结果和SQL是Hibernate使用是如下:

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。

起亚

回答

6

获取副本从一个复杂的休眠条件查询是一个常见的问题,最简单的解决方法是使用只为这个问题做了一个结果变压器:

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 

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

一个更好的解决方案可能是用SubQuery.exists代替部分限制条件,以获得一个子选择来检查是否存在匹配,而不是检索所有匹配,但这可能很难找出。