web-dev-qa-db-ja.com

HQLでDistinctクエリを作成する方法

HQLでDistinctクエリを作成する方法はありますか。 「distinct」キーワードまたは他の方法を使用します。 distinctがHQLの有効なキーワークであるかどうかはわかりませんが、SQLキーワード「distinct」に相当するHQLを探しています。

96
Mike Pone

ここに使用するhqlのスニペットがあります。 (IDを保護するために名前が変更されました)

String queryString = "select distinct f from Foo f inner join foo.bars as b" +
                " where f.creationDate >= ? and f.creationDate < ? and b.bar = ?";
        return getHibernateTemplate().find(queryString, new Object[] {startDate, endDate, bar});
121
Feet

HQLのdistinctキーワードは、SQLのdistinctキーワードに直接マップしないことに注意してください。

HQLでdistinctキーワードを使用する場合、Hibernateはdistinct SQLキーワードを使用することがありますが、場合によっては結果トランスフォーマーを使用して明確な結果を生成します。たとえば、次のような外部結合を使用している場合:

select distinct o from Order o left join fetch o.lineItems

この場合、SQLレベルで重複を除外することはできないため、HibernateはResultTransformerを使用して重複を除外しますafter SQLクエリが実行されました。

53
Daniel Alexiuc

次回このようなことをする

 Criteria crit = (Criteria) session.
                  createCriteria(SomeClass.class).
                  setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

 List claz = crit.list();
16
Michael

また、Criteria.DISTINCT_ROOT_ENTITYをHibernate HQLクエリで使用することもできます。

例:

Query query = getSession().createQuery("from Java_pojo_name");
query.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return query.list();
9
aadi53

HQLクエリと組み合わせた結果トランスフォーマーにいくつかの問題がありました。試したとき

final ResultTransformer trans = new DistinctRootEntityResultTransformer();
qry.setResultTransformer(trans);

うまくいきませんでした。このように手動で変換する必要がありました。

final List found = trans.transformList(qry.list());

Criteria APIトランスフォーマーは問題なく機能しました。

4
Tadeusz Kopec

私の主なクエリは、モデルでは次のようになりました。

@NamedQuery(name = "getAllCentralFinancialAgencyAccountCd", 
    query = "select distinct i from CentralFinancialAgencyAccountCd i")

そして、私はまだ「明確な」結果と考えられるものを得ていませんでした。これらは、テーブル上の主キーの組み合わせに基づいて区別されました。

そのためDaoImplに1行の変更を追加し、最終的には「明確な」リターンを得ました。たとえば、00を4回表示する代わりに、1回だけ表示します。 DaoImplに追加したコードは次のとおりです。

@SuppressWarnings("unchecked")
public List<CacheModelBase> getAllCodes() {

    Session session = (Session) entityManager.getDelegate();
    org.hibernate.Query q = session.getNamedQuery("getAllCentralFinancialAgencyAccountCd");
    q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); // This is the one line I had to add to make it do a more distinct query.
    List<CacheModelBase> codes;
    codes = q.list();
    return codes;       
}

これがお役に立てば幸いです!繰り返しますが、これは、サービス、dao、およびモデルタイプのプロジェクトを実装するコーディングプラクティスに従う場合にのみ機能する可能性があります。

3
Nathan Mitchell

CUSTOMER_INFORMATIONテーブルにマッピングされた顧客エンティティがあり、顧客の異なるfirstNameのリストを取得するとします。以下のスニペットを使用して同じものを取得できます。

Query distinctFirstName = session.createQuery("select ci.firstName from Customer ci group by ci.firstName");
Object [] firstNamesRows = distinctFirstName.list();

役に立てば幸いです。そのため、ここでは個別のキーワードを使用する代わりにgroup byを使用しています。

また、以前は、複数の列に適用する際に個別のキーワードを使用することは困難でした。たとえば、個別のfirstName、lastName、group byのリストを取得するには、単に機能します。この場合、distinctを使用するのは困難でした。

2
chammu

個別のフィールドを使用するためのHibernate Query Languageの回答があります。 * SELECT DISTINCT(TO_CITY)FROM FLIGHT_ROUTE *を使用できます。 SQL queryを使用すると、文字列リストが返されます。 Entity Classごとに戻り値を使用することはできません。したがって、このタイプの問題を解決するための答えは、-HQLSQLを使用することです。

FROM FLIGHT_ROUTE F WHERE F.ROUTE_ID IN (SELECT SF.ROUTE_ID FROM FLIGHT_ROUTE SF GROUP BY SF.TO_CITY);

SQL queryステートメントから、DISTINCT ROUTE_IDを取得し、リストとして入力しました。 INクエリは、IN(リスト)からの別個のTO_CITYをフィルターします。

戻り型はエンティティBean型です。 AutoComplementのようにAJAXでできます。

大丈夫かもしれません

1
San Lin Naing

このような条件ビルダーで個別のキーワードを使用できます。

CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Orders> query = builder.createQuery(Orders.class);
Root<Orders> root = query.from(Orders.class);
query.distinct(true).multiselect(root.get("cust_email").as(String.class));

そして、モデルクラスにフィールドコンストラクターを作成します。

1
Santosh Singh