Hibernate.org Community Documentation

- 前のページ
- 次のページ

## 第16章 HQL: Hibernate クエリ言語

Hibernate は SQL に非常によく似た (意図的に似せた) 強力な問い合わせ言語を備えています。しかし SQL に似た構文に惑わされないでください。 HQL は完全にオブジェクト指向であり、継承、ポリモーフィズム、関連といった概念を理解します。

## 16.1. 大文字と小文字の区別

クエリは Java のクラス名とプロパティ名を除いて大文字、小文字を区別しません。従って `SeLeCT` は `sELEct` と同じで、かつ `SELECT` とも同じですが `org.hibernate.eg.FOO` は `org.hibernate.eg.Foo` とは違い、かつ `foo.barSet` は `foo.BARSET` とも違います。

このマニュアルでは小文字の HQL キーワードを使用します。大文字のキーワードのクエリの方が読みやすいと感じるユーザーもいると思います。ですが、 Java コード内に埋め込まれたときには見づらいと思います。

## 16.2. from 節

もっとも単純な Hibernate クエリは次の形式です:

    from eg.Cat

This returns all instances of the class `eg.Cat`. You do not usually need to qualify the class name, since `auto-import` is the default. For example:

    from Cat

In order to refer to the `Cat` in other parts of the query, you will need to assign an alias. For example:

    from Cat as cat

このクエリでは `Cat` インスタンスに `cat` という別名を付けています。そのため、後でこのクエリ内で、この別名を使うことができます。 `as` キーワードはオプションです。つまりこのように書くこともできます：

    from Cat cat

直積、あるいは「クロス」結合によって多数のクラスが出現することもあります。

    from Formula, Parameter

    from Formula as form, Parameter as param

ローカル変数の Java のネーミング基準と一致した、頭文字に小文字を使ったクエリの別名を付けることはいい習慣です (例えば `domesticCat`)。

## 16.3. 関連と結合

関連するエンティティあるいは値コレクションの要素にも、 `結合` を使って別名を割り当てることが出来ます。

    from Cat as cat
        inner join cat.mate as mate
        left outer join cat.kittens as kitten

    from Cat as cat left join cat.mate.kittens as kittens

    from Formula form full join form.parameter param

サポートしている結合のタイプは ANSI SQL と同じです。

- `inner join`

- `left outer join`

- `right outer join`

- `full join` (たいていの場合使いづらい)

`inner join`、 `left outer join`、 `right outer join` には省略形を使うこともできます。

    from Cat as cat
        join cat.mate as mate
        left join cat.kittens as kitten

HQL の `with` キーワードを使うと、結合条件を付け加えることができます。

    from Cat as cat
        left join cat.kittens as kitten
            with kitten.bodyWeight
    > 10.0

A "fetch" join allows associations or collections of values to be initialized along with their parent objects using a single select. This is particularly useful in the case of a collection. It effectively overrides the outer join and lazy declarations of the mapping file for associations and collections. See 「フェッチ戦略」 for more information.

    from Cat as cat
        inner join fetch cat.mate
        left join fetch cat.kittens

結合によるフェッチは関連するオブジェクトが `where` 節 (または他のどんな節でも) で使われてはならないので、通常別名を割り当てる必要がありません。また関連オブジェクトは問い合わせ結果として直接返されません。代わりに親オブジェクトを通してアクセスできます。コレクションを再帰的に結合フェッチする場合のみ、別名が必要になります:

    from Cat as cat
        inner join fetch cat.mate
        left join fetch cat.kittens child
        left join fetch child.kittens

`fetch` 構文は `iterate()` を使ったクエリ呼び出しで使用できないことに注意してください （一方で `scroll()` は使用できます）。また、これらの操作は結果の行に基づいているため、 `fetch` は `setMaxResults()` や `setFirstResult()` と一緒に使用すべきではありません。通常 eager なコレクションフェッチをすると重複が出てしまうため、あなたが期待するような行数にはならないのです。そしてまた `fetch` は、アドホックな `with` 条件を一緒に使うこともできません。一つのクエリで複数のコレクションを結合フェッチすることにより直積を作成できるので、この場合注意してください。また、複数のコレクションに対する結合フェッチは bag マッピングに対して予期せぬ結果をもたらすことがあるので、この場合のクエリの作成には注意してください。最後に `全外部結合によるフェッチ` と `右外部結合によるフェッチ` は有用ではないことに注意してください。

もしプロパティレベルの遅延フェッチを使う場合（内部的にバイトコード処理をする場合）、 `fetch all properties` を使うことで Hibernate に遅延プロパティを速やかに（最初のクエリで）フェッチさせることができます。

    from Document fetch all properties order by name

    from Document doc fetch all properties where lower(doc.name) like '%cats%'

## 16.4. 結合構文の形式

HQL は２つの関連結合形式をサポートします： `暗黙的` と `明示的`。

これまでのセクションでお見せした使い方はすべて `明示的な` 形式で、 from 節で明示的に join キーワードを使っています。この形式をおすすめします。

`暗黙的` フォームは、 join キーワードを使いません。代わりに、参照する関連にドット表記を使います。 `暗黙的` 結合は、さまざまな HQL に出てきます。 `暗黙的` 結合の結果は、 SQL ステートメントの内部結合結果です。

    from Cat as cat where cat.mate.name like '%s%'

## 16.5. 識別子プロパティの参照

エンティティの識別子プロパティは、一般的に2つの方法で参照されます:

- 特別なプロパティ (小文字) `id` は、 id と名付けられた非識別子プロパティを定義しないエンティティを与えられた エンティティの識別子プロパティを参照するのに使用されます。

- もしエンティティが名付けられた識別子プロパティを定義したら、そのプロパティ名を使用できます。

複合識別子プロパティへの参照は同じ命名ルールに従います。もしエンティティが id と名付けられた非識別子プロパティを持っていたら、複合識別子プロパティはその定義された名前で参照することができます。そうでないと、特別な `id` プロパティは、識別子プロパティを参照するのに使用されます。

## 重要項目

注記: これは、バージョン 3.2.2 から大幅に変更しました。前バージョンでは、 `id` は、その実際の名前に関係なく 常に 識別子プロパティを参照していました。その結果、 `id` と名付けられた非識別子プロパティは、 Hibernate で決して参照されませんでした。

## 16.6. Select 節

`select` 節は以下のようにどのオブジェクトと属性をクエリリザルトセットに返すかを選択します:

    select mate
    from Cat as cat
        inner join cat.mate as mate

上記のクエリは他の `Cat` の `mate` を選択します。実際には次のように、より簡潔に表現できます:

    select cat.mate from Cat cat

クエリはコンポーネント型のプロパティを含む、あらゆる値型のプロパティも返せます:

    select cat.name from DomesticCat cat
    where cat.name like 'fri%'

    select cust.name.firstName from Customer as cust

クエリは複数のオブジェクトと (または) プロパティを `Object[]` 型の配列として返せます。

    select mother, offspr, mate.name
    from DomesticCat as mother
        inner join mother.mate as mate
        left outer join mother.kittens as offspr

もしくは `List` として、

    select new list(mother, offspr, mate.name)
    from DomesticCat as mother
        inner join mother.mate as mate
        left outer join mother.kittens as offspr

あるいは `Family` クラスが適切なコンストラクタを持っているとするならば、

    select new Family(mother, mate, offspr)
    from DomesticCat as mother
        join mother.mate as mate
        left join mother.kittens as offspr

select 節に `as` を使って別名をつけることもできます。

    select max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n
    from Cat cat

`select new map` と一緒に使うときに最も役立ちます：

    select new map( max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n )
    from Cat cat

このクエリは別名から select した値へ `Map` を返します。

## 16.7. 集約関数

HQL のクエリはプロパティの集約関数の結果も返せます：

    select avg(cat.weight), sum(cat.weight), max(cat.weight), count(cat)
    from Cat cat

サポートしている集約関数は以下のものです。

- `avg(...), sum(...), min(...), max(...)`

- `count(*)`

- `count(...), count(distinct ...), count(all...)`

select 節において算術操作、連結と承認された SQL 関数を使うことができます:

    select cat.weight + sum(kitten.weight)
    from Cat cat
        join cat.kittens kitten
    group by cat.id, cat.weight

    select firstName||' '||initial||' '||upper(lastName) from Person

SQL と同じ意味を持つ `distinct` と `all` キーワードを使うことができます。

    select distinct cat.name from Cat cat

    select count(distinct cat.name), count(cat) from Cat cat

## 16.8. ポリモーフィズムを使ったクエリ

次のようなクエリ：

    from Cat as cat

`Cat` インスタンスだけではなく、 `DomesticCat` のようなサブクラスも返されます。 Hibernate クエリは どんな Java クラスやインターフェースも `from` 節に入れることができます。クエリはそのクラスを拡張した、もしくはインターフェースを実装した全ての永続クラスを返します。次のクエリは永続オブジェクトをすべて返します:

    from java.lang.Object o

`Named` インターフェースは様々な永続クラスによって実装されます。:

    from Named n, Named m where n.name = m.name

最後の2つのクエリは、2つ以上の SQL `SELECT` を要求していることに注意してください。このことは `order by` 節がリザルトセット全体を正確には整列しないことを意味します (さらにそれは、 `Query.scroll()` を使用してこれらのクエリを呼ぶことができないことを意味します。)。

## 16.9. where 節

`where` 節は返されるインスタンスのリストを絞ることができます。もし別名がない場合、名前でプロパティを参照します。

    from Cat where name='Fritz'

もし別名がある場合、修飾名を使ってください:

    from Cat as cat where cat.name='Fritz'

名前が 'Fritz' という `Cat` のインスタンスを返します。

The following query:

    select foo
    from Foo foo, Bar bar
    where foo.startDate = bar.date

上の HQL は、 `Foo` の `startDate` プロパティと等しい `date` プロパティを持った `bar` インスタンスが存在する、すべての `Foo` インスタンスを返します。コンパウンドパス式は `where` 節を非常に強力にします。注目：

    from Cat cat where cat.mate.name is not null

このクエリはテーブル結合（内部結合）を持つ SQL クエリに変換されます。その代わりに以下のように書くと、

    from Foo foo
    where foo.bar.baz.customer.address.city is not null

もし上のクエリを記述したらクエリ内に4つのテーブル結合を必要とする SQL クエリに変換されます。

`=` 演算子は以下のように、プロパティだけでなくインスタンスを比較するためにも使われます。：

    from Cat cat, Cat rival where cat.mate = rival.mate

    select cat, mate
    from Cat cat, Cat mate
    where cat.mate = mate

The special property (lowercase) `id` can be used to reference the unique identifier of an object. See 「識別子プロパティの参照」 for more information.

    from Cat as cat where cat.id = 123

    from Cat as cat where cat.mate.id = 69

2番目のクエリは効率的です。テーブル結合が必要ありません。

また複合識別子のプロパティも使用できます。ここで `Person` が `country` と `medicareNumber` からなる複合識別子を持つと仮定します。識別子プロパティ参照についての詳細は、前回と同様に 「識別子プロパティの参照」 を参照ください。

    from bank.Person person
    where person.id.country = 'AU'
        and person.id.medicareNumber = 123456

    from bank.Account account
    where account.owner.id.country = 'AU'
        and account.owner.id.medicareNumber = 123456

繰り返しますが、2番目のクエリにはテーブル結合が必要ありません。

See 「識別子プロパティの参照」 for more information regarding referencing identifier properties)

同様に `class` は特別なプロパティであり、ポリモーフィックな永続化におけるインスタンスの discriminator 値にアクセスします。 where 節に埋め込まれた Java のクラス名はその discriminator 値に変換されます。

    from Cat cat where cat.class = DomesticCat

You can also use components or composite user types, or properties of said component types. See 「コンポーネント」 for more information.

"any" 型は特別なプロパティである `id` と `class` を持ち、以下の方法で結合を表現することを可能にします (`AuditLog.item` は `<any>` でマッピングされたプロパティです)。

    from AuditLog log, Payment payment
    where log.item.class = 'Payment' and log.item.id = payment.id

`log.item.class` と `payment.class` が上記のクエリ中で全く異なるデータベースカラムの値を参照するということに注意してください。

## 16.10. Expressions 式

Expressions used in the `where` clause include the following:

- 算術演算子：`+, -, *, /`

- 2項比較演算子：`=, >=, <=, <>, !=, like`

- 論理演算子：`and, or, not`

- グループ分けを表す括弧：`( )`

- `in`, `not in`, `between`, `is null`, `is not null`, `is empty`, `is not empty`, `member of` and `not member of`

- "シンプル"な case `case ... when ... then ... else ... end`、 "探索的"な case `case when ... then ... else ... end`

- ストリングの連結 `...||...` または `concat(...,...)`

- `current_date()`, `current_time()`, `current_timestamp()`

- `second(...)`, `minute(...)`, `hour(...)`, `day(...)`, `month(...)`, `year(...)`,

- EJB-QL 3.0 で定義されている関数や演算子: `substring(), trim(), lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(), mod()`

- `coalesce()` と `nullif()`

- 数字や時間の値を String にコンバートする `str()`

- 2番目の引数が Hibernate 型の名前である `cast(... as ...)` と `extract(... from ...)`。ただし使用するデータベースが ANSI `cast()` と `extract()` をサポートする場合に限ります。

- 結合したインデックス付きのコレクションの別名に適用される HQL の `index()` 関数。

- コレクション値のパス式を取る HQL 関数： `size(), minelement(), maxelement(), minindex(), maxindex()` 。 `some, all, exists, any, in` を使って修飾することができる特別な `elements()` と `indices` 関数と一緒に使います。

- `sign()`、 `trunc()`、 `rtrim()`、 `sin()` のようなデータベースがサポートする SQL スカラ関数。

- JDBC スタイルの位置パラメータ `?`

- 名前付きパラメータ: `:name`, `:start_date`, `:x1`

- SQL リテラル： `'foo'`、 `69`、 `6.66E+2`、 `'1970-01-01 10:00:01.0'`

- Java の `public static final` 定数： `eg.Color.TABBY`

`in` と `between` は以下のように使用できます:

    from DomesticCat cat where cat.name between 'A' and 'B'

    from DomesticCat cat where cat.name in ( 'Foo', 'Bar', 'Baz' )

また、否定形で記述することもできます。

    from DomesticCat cat where cat.name not between 'A' and 'B'

    from DomesticCat cat where cat.name not in ( 'Foo', 'Bar', 'Baz' )

同様に `is null` や `is not null` は null 値をテストするために使用できます。

Hibernate 設定ファイルで HQL query substitutions を定義すれば、 boolean 値を式の中で簡単に使用できます：

    <property name="hibernate.query.substitutions"
    >true 1, false 0</property
    >

こうすることで下記の HQL を SQL に変換するときに `true` 、 `false` キーワードは `1` 、 `0` に置き換えられます:

    from Cat cat where cat.alive = true

特別なプロパティ `size`、または特別な関数 `size()` を使ってコレクションのサイズをテストできます:

    from Cat cat where cat.kittens.size
    > 0

    from Cat cat where size(cat.kittens)
    > 0

インデックス付きのコレクションでは、 `minindex` と `maxindex` 関数を使って、インデックスの最小値と最大値を参照できます。同様に、 `minelement` と `maxelement` を使って、基本型のコレクション要素の最小値と最大値を参照できます。

    from Calendar cal where maxelement(cal.holidays)
    > current_date

    from Order order where maxindex(order.items)
    > 100

    from Order order where minelement(order.items)
    > 10000

コレクションの要素やインデックスのセット（`elements` と `indices` 関数）、または副問い合わせ（後述）の結果が受け取れるときは、 SQL 関数 `any, some, all, exists, in` がサポートされます。

    select mother from Cat as mother, Cat as kit
    where kit in elements(foo.kittens)

    select p from NameList list, Person p
    where p.name = some elements(list.names)

    from Cat cat where exists elements(cat.kittens)

    from Player p where 3
    > all elements(p.scores)

    from Show show where 'fizard' in indices(show.acts)

`size`、 `elements`、 `indices`、 `minindex`、 `maxindex`、 `minelement`、 `maxelement` は Hibernate3 の where 節だけで利用可能であることに注意してください。

インデックス付きのコレクション（arrays, lists, maps）の要素は、インデックスで参照できます（where節内でのみ）：

    from Order order where order.items[0].id = 1234

    select person from Person person, Calendar calendar
    where calendar.holidays['national day'] = person.birthDay
        and person.nationality.calendar = calendar

    select item from Item item, Order order
    where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11

    select item from Item item, Order order
    where order.items[ maxindex(order.items) ] = item and order.id = 11

`[]` 内部の式は、算術式でも構いません。

    select item from Item item, Order order
    where order.items[ size(order.items) - 1 ] = item

一対多関連や値のコレクションの要素に対しては、 HQL は組み込みの `index()` 関数も用意しています。

    select item, index(item) from Order order
        join order.items item
    where index(item) < 5

ベースとなるデータベースがサポートしているスカラー SQL 関数が使用できます：

    from DomesticCat cat where upper(cat.name) like 'FRI%'

もしまだ全てを理解していないなら、下のクエリを SQL でどれだけ長く、読みづらく出来るか考えてください:

    select cust
    from Product prod,
        Store store
        inner join store.customers cust
    where prod.name = 'widget'
        and store.location.name in ( 'Melbourne', 'Sydney' )
        and prod = all elements(cust.currentOrder.lineItems)

ヒント: 例えばこのように出来ます。

    SELECT cust.name, cust.address, cust.phone, cust.id, cust.current_order
    FROM customers cust,
        stores store,
        locations loc,
        store_customers sc,
        product prod
    WHERE prod.name = 'widget'
        AND store.loc_id = loc.id
        AND loc.name IN ( 'Melbourne', 'Sydney' )
        AND sc.store_id = store.id
        AND sc.cust_id = cust.id
        AND prod.id = ALL(
            SELECT item.prod_id
            FROM line_items item, orders o
            WHERE item.order_id = o.id
                AND cust.current_order = o.id
        )

## 16.11. order by 節

クエリが返す list は、返されるクラスやコンポーネントの任意の属性によって並べ替えられます：

    from DomesticCat cat
    order by cat.name asc, cat.weight desc, cat.birthdate

オプションの `asc` と `desc` はそれぞれ昇順か降順の整列を示します。

## 16.12. group by 節

集約値を返すクエリは、返されるクラスやコンポーネントの任意のプロパティによってグループ化できます:

    select cat.color, sum(cat.weight), count(cat)
    from Cat cat
    group by cat.color

    select foo.id, avg(name), max(name)
    from Foo foo join foo.names name
    group by foo.id

`having` 節も使えます。

    select cat.color, sum(cat.weight), count(cat)
    from Cat cat
    group by cat.color
    having cat.color in (eg.Color.TABBY, eg.Color.BLACK)

もし使用するデータベースがサポートしているなら、 `having` と `order by` 節で SQL 関数と集約関数が使えます（例えば MySQL にはありません）。

    select cat
    from Cat cat
        join cat.kittens kitten
    group by cat.id, cat.name, cat.other, cat.properties
    having avg(kitten.weight)
    > 100
    order by count(kitten) asc, sum(kitten.weight) desc

`group by` 節や `order by` 節に算術式を含むことができないことに注意してください。また、 Hibernate は今のところグループエンティティを拡張しないことにも注意してください。したがって、もし `cat` の全てのプロパティが非集合体の場合、 `group by cat` を書くことはできません。全ての非集合体のプロパティを明示的にリストする必要があります。

## 16.13. 副問い合わせ

サブセレクトをサポートするデータベースのため、 Hibernate は副問い合わせをサポートしています。副問い合わせは括弧で囲まなければなりません（ SQL の集約関数呼び出しによる事が多いです）。関連副問い合わせ (外部クエリ中の別名を参照する副問い合わせのこと) さえ許可されます。

    from Cat as fatcat
    where fatcat.weight
    > (
        select avg(cat.weight) from DomesticCat cat
    )

    from DomesticCat as cat
    where cat.name = some (
        select name.nickName from Name as name
    )

    from Cat as cat
    where not exists (
        from Cat as mate where mate.mate = cat
    )

    from DomesticCat as cat
    where cat.name not in (
        select name.nickName from Name as name
    )

    select cat.id, (select max(kit.weight) from cat.kitten kit)
    from Cat as cat

HQL 副問い合わせは、 select または where 節だけで使われることに注意してください。

Note that subqueries can also utilize `row value constructor` syntax. See 「行値コンストラクタ構文」 for more information.

## 16.14. HQL の例

Hibernate クエリは非常に強力で複雑にできます。実際、クエリ言語の威力は Hibernate の主要なセールスポイントの一つです。ここに最近のプロジェクトで使用したクエリと非常によく似た例があります。ほとんどのクエリはこれらの例より簡単に記述できることに注意してください。

以下のクエリは特定の顧客と与えられた最小の合計値に対する未払い注文の注文 ID 、商品の数、注文の合計を合計値で整列して返します。価格を決定する際、現在のカタログを使います。結果として返される SQL クエリは `ORDER`、 `ORDER_LINE`、 `PRODUCT`、 `CATALOG` および `PRICE` テーブルに対し4つの内部結合と (関連しない) 副問い合わせを持ちます。

    select order.id, sum(price.amount), count(item)
    from Order as order
        join order.lineItems as item
        join item.product as product,
        Catalog as catalog
        join catalog.prices as price
    where order.paid = false
        and order.customer = :customer
        and price.product = product
        and catalog.effectiveDate < sysdate
        and catalog.effectiveDate
    >= all (
            select cat.effectiveDate
            from Catalog as cat
            where cat.effectiveDate < sysdate
        )
    group by order
    having sum(price.amount)
    > :minAmount
    order by sum(price.amount) desc

何て巨大なクエリなのでしょう。普段私は副問い合わせをあまり使いません。したがって私のクエリは実際には以下のようになります。:

    select order.id, sum(price.amount), count(item)
    from Order as order
        join order.lineItems as item
        join item.product as product,
        Catalog as catalog
        join catalog.prices as price
    where order.paid = false
        and order.customer = :customer
        and price.product = product
        and catalog = :currentCatalog
    group by order
    having sum(price.amount)
    > :minAmount
    order by sum(price.amount) desc

次のクエリは各ステータスの支払い数を数えます。ただしすべての支払いが現在の利用者による最新のステータス変更である `AWAITING_APPROVAL` である場合を除きます。このクエリは2つの内部結合と `PAYMENT`, `PAYMENT_STATUS` および `PAYMENT_STATUS_CHANGE` テーブルに対する関連副問い合わせを備えた SQL クエリに変換されます。

    select count(payment), status.name
    from Payment as payment
        join payment.currentStatus as status
        join payment.statusChanges as statusChange
    where payment.status.name <
    > PaymentStatus.AWAITING_APPROVAL
        or (
            statusChange.timeStamp = (
                select max(change.timeStamp)
                from PaymentStatusChange change
                where change.payment = payment
            )
            and statusChange.user <
    > :currentUser
        )
    group by status.name, status.sortOrder
    order by status.sortOrder

もし set の代わりに list として `statusChanges` コレクションをマッピングしたならば、はるかに簡単にクエリを記述できるでしょう。

    select count(payment), status.name
    from Payment as payment
        join payment.currentStatus as status
    where payment.status.name <
    > PaymentStatus.AWAITING_APPROVAL
        or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <
    > :currentUser
    group by status.name, status.sortOrder
    order by status.sortOrder

次のクエリは現在のユーザーが所属する組織に対するアカウントおよび未払いの支払いをすべて返す MS SQL Server の `isNull()` 関数を使用しています。このクエリは3つの内部結合と1つの外部結合、そして `ACCOUNT`、 `PAYMENT`、 `PAYMENT_STATUS`、 `ACCOUNT_TYPE`、 `ORGANIZATION` および `ORG_USER` テーブルに対する副問い合わせ持った SQL に変換されます。

    select account, payment
    from Account as account
        left outer join account.payments as payment
    where :currentUser in elements(account.holder.users)
        and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
    order by account.type.sortOrder, account.accountNumber, payment.dueDate

いくつかのデータベースについては、 (関連させられた) 副問い合わせの使用を避ける必要があるでしょう。

    select account, payment
    from Account as account
        join account.holder.users as user
        left outer join account.payments as payment
    where :currentUser = user
        and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
    order by account.type.sortOrder, account.accountNumber, payment.dueDate

## 16.15. 大量の UPDATE と DELETE

HQL now supports `update`, `delete` and `insert ... select ...` statements. See 「DML スタイルの操作」 for more information.

## 16.16. Tips & Tricks

実際に結果を返さなくてもクエリの結果数を数えることができます:

    ( (Integer) session.createQuery("select count(*) from ....").iterate().next() ).intValue()

コレクションのサイズにより結果を並べ替えるためには以下のクエリを使用します:

    select usr.id, usr.name
    from User as usr
        left join usr.messages as msg
    group by usr.id, usr.name
    order by count(msg)

使用しているデータベースがサブセレクトをサポートする場合、クエリの where 節でサイズによる選択条件を設定できます:

    from User usr where size(usr.messages)
    >= 1

使用しているデータベースがサブセレクトをサポートしない場合は、次のクエリを使用してください:

    select usr.id, usr.name
    from User usr
        join usr.messages msg
    group by usr.id, usr.name
    having count(msg)
    >= 1

内部結合をしているせいで上の解決法が message の件数がゼロの `User` を返すことができないならば、以下の形式が使えます:

    select usr.id, usr.name
    from User as usr
        left join usr.messages as msg
    group by usr.id, usr.name
    having count(msg) = 0

JavaBean のプロパティは、名前付きのクエリパラメータに結びつけることが出来ます：

    Query q = s.createQuery("from foo Foo as foo where foo.name=:name and foo.size=:size");

    q.setProperties(fooBean); // fooBean has getName() and getSize()

    List foos = q.list();

コレクションはフィルタ付き `Query` インターフェースを使用することでページをつけることができます:

    Query q = s.createFilter( collection, "" ); // the trivial filter

    q.setMaxResults(PAGE_SIZE);

    q.setFirstResult(PAGE_SIZE * pageNumber);

    List page = q.list();

コレクションの要素はクエリフィルタを使って、並べ替えやグループ分けが出来ます:

    Collection orderedCollection = s.filter( collection, "order by this.amount" );

    Collection counts = s.filter( collection, "select this.type, count(this) group by this.type" );

コレクションを初期化せずにコレクションのサイズを得ることができます:

    ( (Integer) session.createQuery("select count(*) from ....").iterate().next() ).intValue();

## 16.17. コンポーネント

HQL クエリでシンプルな値型を使用できるので、コンポーネントは、あらゆる点で使用できます。これは `select` 節の中に現われます:

    select p.name from Person p

    select p.name.first from Person p

人名のプロパティがコンポーネントの場所。コンポーネントは、 `where` 節でも使用可能です:

    from Person p where p.name = :name

    from Person p where p.name.first = :firstName

コンポーネントは `order by` 節でも使用可能です:

    from Person p order by p.name

    from Person p order by p.name.first

Another common use of components is in row value constructors.

## 16.18. 行値コンストラクタ構文

下に位置するデータベースが ANSI SQL `row value constructor` 構文 (`tuple` 構文とよばれることもあります) をサポートしていないとしても、 HQL はその使用をサポートしています。ここでは、一般的にコンポーネントと連繋するマルチバリュー比較について触れます。ネームコンポーネントを定義する Person エンティティを考えましょう:

    from Person p where p.name.first='John' and p.name.last='Jingleheimer-Schmidt'

それは少々詳細になりますが、有効な構文です。より簡潔にし、 `row value constructor` 構文を使用するのがよいでしょう:

    from Person p where p.name=('John', 'Jingleheimer-Schmidt')

それを `select` 節で指定するのも効果的です。

    select p.name from Person p

次に `row value constructor` 構文の使用が有効なときは、サブクエリを使用して複数の値と比較する必要があるときです:

    from Cat as cat
    where not ( cat.name, cat.color ) in (
        select cat.name, cat.color from DomesticCat cat
    )

この構文を使用するかどうか決定するときに考慮しなければならないことは、クエリがメタデータ内のコンポーネントのサブプロパティの順番に依存していることです。

製作著作 © 2004 Red Hat, Inc.

- 前のページ第15章 バッチ処理
- 上に戻る
- ホーム
- 次のページ第17章 Criteria クエリ