5

UserクラスとUserGroupクラスがあると仮定します。オプションの1対多のグループからユーザーへの関連付けがあり、関連付けは両側からマップされます(HashSetである「members」と呼ばれるプロパティを介したUserGroup側、プロパティ「group」を介したユーザー側)。

Criteria APIを使用して、グループメンバーの数でソートされたすべてのグループをクエリするにはどうすればよいですか?

(編集)SQLでページネーションが行われていることを聞いたときに指摘しておくべきだったので、可能であればSQLでも順序付けを行う必要があります。

4

3 に答える 3

5

デフォルトでは 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();

これにより、メンバーのサイズの昇順で並べ替えられたユーザー グループが一覧表示されます。ここで、「メンバー」は UserGroup エンティティのユーザー コレクションです。

于 2012-08-28T11:20:50.453 に答える
2

別のオプションは、ネストされた選択を作成するのと基本的に同等の @Formula アノテーションを使用して、カウントを取得できるようにすることです。

問題のDBオブジェクトのプロパティ/メンバー(作成する必要があります)で、次のように注釈をゲッターに追加します。

@Formula("(SELECT COUNT(TABLE_NAME.ID) FROM TABLE WHERE 何でも...)") public long getNewProperty{ return newProperty; }

次に、メンバーを直接ターゲットにして、カウント値を取得します...

注: 数式注釈内で sql を指定する場合、hibernate が this 自体を処理するため、現在のオブジェクト テーブル (this) を参照するときにフィールド名を直接指定する必要があることに注意してください。したがって、WHERE句では、UserGroupであると思われる現在のオブジェクトテーブルを参照するときに、IDなどを単独で使用してください。

休止状態が機能し、コンパイラが不平を言うのを防ぐために、新しいプロパティのセッターが必要でした。

@Formula を使用する他の賢い方法があるかもしれませんが、私はこれにかなり慣れていないため、この件に関するドキュメントはあまりないようです...

以前にネストされた SELECTS を使用したことがない場合は、最初に sql で再作成することをお勧めします - それは私を助けました.

お役に立てれば

于 2009-08-31T08:29:28.703 に答える
0

おそらくこれは、エンティティに「派生プロパティ」を定義することで実現できます。これは、そのエンティティ内のコレクションのサイズを返す読み取り専用プロパティになります。派生プロパティを定義する最も簡単な方法は、次のドキュメントに記載されています

update、insert (オプション - デフォルトは true): マップされた列を SQL UPDATE および/または INSERT ステートメントに含める必要があることを指定します。両方を false に設定すると、値が同じ列にマップされる他のプロパティから、またはトリガーまたは他のアプリケーションによって初期化される、純粋な「派生」プロパティが許可されます。

プロパティが定義されると、他のプロパティと同様に、条件 API でプロパティ名を順序句として使用できるようになります。ただし、私はこれを自分で試したことはありません。

それが機能する場合、SQL にマップできないため、メモリ内ソートとして実行される可能性があります。これが問題である場合は、上記の同じリンクに、カスタム SQL フラグメントを使用して派生プロパティを実装する方法が記載されています。

強力な機能は派生プロパティです。これらのプロパティは、定義上、読み取り専用です。プロパティ値は読み込み時に計算されます。計算を SQL 式として宣言します。これは、インスタンスをロードする SQL クエリの SELECT 句のサブクエリに変換されます。

于 2009-08-10T11:24:00.880 に答える