Hibernate Criteria API - 컬렉션 크기별로 주문하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1254306

  •  12-09-2019
  •  | 
  •  

문제

User 및 UserGroup 클래스가 있다고 가정합니다.사용자 연결에는 선택적인 1-다 그룹이 있으며 연결은 양쪽에서 매핑됩니다(UserGroup 쪽은 HashSet인 "members"라는 속성을 통해, 사용자 쪽은 "group" 속성을 통해).

Criteria API를 사용하여 그룹 구성원 수를 기준으로 정렬된 모든 그룹을 쿼리하려면 어떻게 해야 합니까?

(편집) 내가 이것을 물었을 때 SQL에서 페이지 매김이 수행되고 있으므로 순서 지정도 가능하면 SQL에서 수행되어야 함을 지적했어야 했습니다.

도움이 되었습니까?

해결책

또 다른 옵션은 기본적으로 중첩 선택을 생성하는 것과 동일한 @Formula 주석을 사용하여 계산할 수 있는 것입니다.

문제의 DB 객체 속성/멤버(생성해야 함)에서 다음과 같이 getter에 주석을 추가합니다.

@Formula("(SELECT COUNT(TABLE_NAME.ID) FROM TABLE WHERE 무엇이든...)") 공개 긴 getNewProperty{ newProperty 반환;}

그런 다음 회원을 직접 타겟팅하여 카운트 값을 확인하세요.

메모:수식 주석 내에서 SQL을 지정할 때 최대 절전 모드가 이 자체를 처리하므로 현재 개체 테이블(this)을 참조할 때 필드 이름을 직접 지정해야 한다는 점에 유의하세요.따라서 WHERE 절에서 UserGroup으로 의심되는 현재 개체 테이블을 참조할 때 ID 등을 자체적으로 사용하세요.

최대 절전 모드가 작동하고 컴파일러가 불평하는 것을 방지하려면 새 속성에 대한 설정자가 있어야 했습니다.

@Formula를 사용하는 다른 영리한 방법이 있을 수 있지만 저는 이 방법이 처음이고 해당 주제에 대한 문서가 별로 없는 것 같습니다.

이전에 중첩된 SELECTS를 사용해 본 적이 없다면 먼저 SQL에서 다시 생성하는 것이 도움이 될 수 있습니다.

도움이 되었기를 바랍니다

다른 팁

Citeria API를 사용하는 것은 기본적으로 불가능하지만 org.hibernate.criterion.Order 클래스를 확장할 수 있습니다.이 문서는 해당 클래스를 확장하는 방법에 관한 것입니다. http://blog.tremend.ro/2008/06/10/how-to-order-by-a-custom-sql-formulaexpression-when-using-hibernate-criteria-api

내 해결책은 다음과 같습니다.

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

이렇게 하면 구성원 크기에 따라 오름차순으로 정렬된 사용자 그룹이 나열됩니다. 여기서 "members"는 UserGroup 엔터티의 사용자 컬렉션입니다.

해당 엔터티 내부의 컬렉션 크기를 반환하는 읽기 전용 속성인 "파생 속성"을 엔터티에 정의하여 이를 수행할 수 있습니다.파생 속성을 정의하는 가장 쉬운 방법은 다음과 같습니다. 여기에 문서화되어 있습니다:

update, insert (옵션 - 디폴트는 true)를 사용합니다.매핑된 열은 SQL에 포함되어야 합니다. UPDATE 및/또는 INSERT 문.둘 다 false로 설정하면 순수 값이 "derived" 속성입니다. 다른 속성에서 초기화됨 동일한 열에 매핑되거나 트리거 또는 다른 응용 프로그램.

속성이 정의되면 다른 속성과 마찬가지로 기준 API에서 속성 이름을 순서 절로 사용할 수 있습니다.하지만 나는 이것을 직접 시도하지 않았습니다.

작동한다면 SQL에 매핑할 수 없으므로 메모리 내 정렬로 수행될 가능성이 높습니다.이것이 문제인 경우 위의 동일한 링크는 사용자 정의 SQL 조각을 사용하여 파생 속성을 구현하는 방법을 문서화합니다.

강력한 기능이 파생됩니다 속성.이러한 속성은 다음과 같습니다. definition 읽기 전용입니다.숙소 일반 정보 value는 로드 시 계산됩니다.너 계산을 SQL로 선언 식.그러면 SQL의 SELECT 절 하위 쿼리 인스턴스를 로드하는 쿼리:

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top