2009-08-10 2 views
3

클래스 User 및 UserGroup이 있다고 가정합니다. 사용자 연결에 대한 선택적인 1 - many 그룹이 있으며, 연결은 양측에서 매핑됩니다 (HashSet 인 "members"라는 속성을 통해 UserGroup 측, "group"속성을 통해 사용자 측).Hibernate Criteria API - 컬렉션 크기에 따라 정렬하는 방법?

기준 API를 사용하면 그룹 구성원 수로 정렬하여 모든 그룹을 쿼리 할 수 ​​있습니까?

(편집)이 페이지 매김이 SQL에서 수행 중이라는 것을 지적 했어야했기 때문에 가능한 경우 SQL에서 순서를 수행해야했습니다.

답변

1

또 다른 옵션은 그래서 당신이 얻을 수 기본적으로는 선택 중첩 만드는 것과 같습니다 @Formula 주석을 사용하는 것입니다 귀하의 카운트. WHERE 어떤 테이블에서

@Formula ("(SELECT COUNT (TABLE_NAME.ID) .. : 당신의 DB에

가 (당신이 작성해야합니다) 문제의 특성/회원 객체, 같은 게터에 주석을 추가 .) ") public long getNewProperty { return newProperty;

이 그런 다음 카운트 값 잡아 직접 회원을 대상으로 } ...

참고 : 수식 주석 내에서 SQL을 지정할 때 전류를 참조 할 때, 직접 필드 이름을 지정해야합니다주의 objects 테이블 (this)은 hibernate가 이것 자체를 다룬다. 따라서 WHERE 절에서 UserGroup이라는 의심이있는 현재 객체 테이블을 참조 할 때 ID 나 그 자체로 무엇이든 사용하십시오.

나는 hibernate가 작동하고 컴파일러가 불평하는 것을 막기 위해 새로운 속성에 대한 세터를 가져야 만했다.

이 @Formula를 사용하는 다른 현명한 방법이 될,하지만이 아주 새로운 해요 및 주제에 매우 문서가있을 나타나지 않을 수 있습니다 ...

사용한 적이 없다면 중첩 된 SELECTS를 사용하기 전에 SQL에서 처음부터 다시 만들면 도움이 될 것입니다.

희망이 Citeria API를 사용하여 기본적으로 그것은 불가능하다

+0

이 구현은 약간 의심 스럽지만 (최대 절전 모드 문서의 관점에서) 실제로 작동합니까? – ireddick

0

엔티티에서 "파생 된 속성"을 정의하면 해당 엔티티 내부의 컬렉션 크기를 반환하는 읽기 전용 속성이 될 수 있습니다. 매핑 된 열은 SQL UPDATE 및/또는 INSERT 문에 포함되도록 지정 : - (참 디폴트 옵션)

업데이트, 삽입 : 파생 속성을 정의하는 가장 쉬운 방법은 documented here입니다. 둘 다 false로 설정하면 순수 값이 인 "derived"속성이 동일한 열로 매핑되는 다른 속성 에서 초기화되거나 이 트리거 또는 다른 응용 프로그램으로 초기화됩니다.

일단 속성이 정의되면 다른 속성과 마찬가지로 조건 API의 순서 절로 속성 이름을 사용할 수 있어야합니다. 나는 이것을 시도하지 않았다.

작동하는 경우 SQL에 매핑 할 수 없으므로 메모리 내 정렬로 처리 될 가능성이 큽니다. 이 문제가 있다면, 문서 위와 같은 링크는 사용자 정의 SQL 조각을 사용하여 파생 속성을 구현하는 방법 :

강력한 기능은 속성을 파생됩니다. 이러한 속성은 정의 읽기 전용입니다. 속성 값은로드시 계산됩니다. 계산을 SQL 표현식으로 선언하십시오. 이 후 인스턴스를로드하는 SQL 쿼리에 SELECT 절 서브 쿼리로 변환 :

3

을 할 수 있지만 org.hibernate.criterion.Order 클래스를 확장 할 수 있습니다. http://blog.tremend.ro/2008/06/10/how-to-order-by-a-custom-sql-formulaexpression-when-using-hibernate-criteria-api

내 sollution은 다음과 같습니다 :

public class SizeOrder extends Order { 

    protected String propertyName; 
    protected boolean ascending; 

    protected SizeOrder(String propertyName, boolean ascending) { 
     super(propertyName, ascending); 
     this.propertyName = propertyName; 
     this.ascending = ascending; 
    } 

    public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { 
     String role = criteriaQuery.getEntityName(criteria, propertyName) + '.' + criteriaQuery.getPropertyName(propertyName); 
     QueryableCollection cp = (QueryableCollection) criteriaQuery.getFactory().getCollectionPersister(role); 

     String[] fk = cp.getKeyColumnNames(); 
     String[] pk = ((Loadable) cp.getOwnerEntityPersister()) 
       .getIdentifierColumnNames(); 
     return " (select count(*) from " + cp.getTableName() + " where " 
       + new ConditionFragment() 
         .setTableAlias(
           criteriaQuery.getSQLAlias(criteria, propertyName) 
         ).setCondition(pk, fk) 
        .toFragmentString() + ") " 
       + (ascending ? "asc" : "desc"); 
    } 

    public static SizeOrder asc(String propertyName) { 
     return new SizeOrder(propertyName, true); 
    } 
    public static SizeOrder desc(String propertyName) { 
     return new SizeOrder(propertyName, false); 
    } 
} 

toSqlString 방법은 org.hibernate.criterion.SizeExpression 클래스를 기반으로 이 문서는 클래스를 확장하는 방법에 관한 것입니다. (출처 : http://javasourcecode.org/html/open-source/hibernate/hibernate-3.6.0.Final/org/hibernate/criterion/SizeExpression.java.html)

사용 예제는 :

hibernateSession.createCriteria(UserGroup.class).addOrder(SizeOrder.asc("members")).list(); 

이 "회원"사용자 그룹 엔티티에 사용자의 모음입니다 오름차순 회원의 크기에 의해 정렬 된 사용자 그룹을 나열합니다.

관련 문제