Hibernate アプリケーションの開発

Red Hat JBoss Enterprise Application Platform 7.4

Red Hat JBoss Enterprise Application Platform 向けの Jakarta Persistence API (JPA) または Hibernate アプリケーションを開発およびデプロイする開発者および管理者のための手順と情報。

概要

本書は、Red Hat JBoss Enterprise Application Platform で Jakarta Persistence/Hibernate アプリケーションの開発とデプロイを行う開発者と管理者に情報を提供します。

Red Hat ドキュメントへのフィードバック

弊社のドキュメントに関するご意見やご感想をお寄せください。フィードバックをお寄せいただくには、ドキュメントのテキストを強調表示し、コメントを追加できます。以下の手順に従って、Red Hat ドキュメントのフィードバックをお寄せください。

要件

  • Red Hat カスタマーポータルにログインします。
  • Red Hat カスタマーポータルで、Multi-page HTML 形式のドキュメントを表示します。

手順

  1. フィードバック をクリックして、既存のリーダーコメントを表示します。

    注記

    フィードバック機能は、マルチページ HTML 形式でのみ有効です。

  2. フィードバックを提供するドキュメントのセクションを強調表示します。
  3. 選択したテキストの近くに表示されるプロンプトメニューで、Add Feedback をクリックします。

    ページの右側のフィードバックセクションにテキストボックスが開きます。

  4. テキストボックスにフィードバックを入力し、Submit をクリックします。

    ドキュメントに関する問題を作成しました。

  5. 問題を表示するには、フィードバックビューで問題トラッカーリンクをクリックします。

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。まずは、マスター (master)、スレーブ (slave)、ブラックリスト (blacklist)、ホワイトリスト (whitelist) の 4 つの用語の置き換えから始めます。この取り組みは膨大な作業を要するため、今後の複数のリリースで段階的に用語の置き換えを実施して参ります。詳細は、弊社 の CTO、Chris Wright のメッセージ を参照してください。

第1章 はじめに

1.1. Hibernate Core

Hibernate Core は、Java 言語用のオブジェクト関係マッピングフレームワークです。これにより、オブジェクト指向のドメインモデルをリレーショナルデータベースにマップするフレームワークが提供されるため、アプリケーションはデータベースとの直接的な対話を回避できます。Hibernate は、直接の永続データベースアクセスを高レベルのオブジェクト処理関数に置き換えることで、オブジェクト関係の不一致の問題を解決します。

1.2. Hibernate EntityManager

Hibernate EntityManager は、Jakarta Persistence 2.2 仕様で定義されているプログラミングインターフェースおよびライフサイクルルールを実装します。Hibernate Annotations とともに、このラッパーは成熟した Hibernate Core の上に完全な (およびスタンドアロン) Jakarta Persistence ソリューションを実装します。プロジェクトのビジネスニーズおよび技術上のニーズに応じて、Jakarta Persistence プログラミングインターフェースやライフサイクル、あるいは純粋なネイティブ Hibernate Core でさえすべて組み合わせて使用できます。いつでも、Hibernate ネイティブ API、または必要に応じてネイティブ JDBC および SQL にフォールバックできます。JBoss EAP には完全な Jakarta 永続ソリューションが提供されます。

JBoss EAP 7.3 以降のリリースは、Jakarta EE 8 で定義された Jakarta Persistence 2.2 仕様に準拠し ています。

また、Hibernate によってこの仕様に追加機能が提供されます。Jakarta Persistence および JBoss EAP を初めて使用する場合は、JBoss EAP に同梱される bean-validationgreeter、および kitchensink クイックスタートを参照してください。

Jakarta Persistence は、Jakarta Enterprise Beans 3 または、より新しい Jakarta Contexts and Dependency Injection などのコンテナーや、特定コンテナーの外部で実行するスタンドアロン Java SE アプリケーションで利用できます。以下のプログラミングインターフェースおよびアーティファクトは、両方の環境で利用できます。

重要

Hibernate でセキュリティーマネージャーの使用を計画している場合は、EntityManagerFactory が JBoss EAP サーバーによってブートストラップされている場合のみ Hibernate がサポートすることに注意してください。EntityManagerFactory または SessionFactory がアプリケーションによってブートストラップされている場合はサポートされません。

EntityManagerFactory
エンティティーマネージャーファクトリーはエンティティーマネージャーインスタンスを提供し、すべてのインスタンスは同じデータベースに接続するよう設定され、特定の実装で定義されたのと同じデフォルト設定を使用します。複数のデータストアにアクセスするための複数のエンティティーマネージャーファクトリーを準備できます。このインターフェースは、ネイティブ Hibernate の SessionFactory と似ています。
EntityManager
EntityManager API は、特定の作業単位でデータベースにアクセスするために使用されます。これは、永続的なエンティティーインスタンスの作成および削除、それらのプライマリーキーアイデンティティーによるエンティティーの検索、およびすべてのエンティティーのクエリーに使用されます。このインターフェースは、Hibernate の Session と似ています。
永続コンテキスト
永続コンテキストは、すべての永続エンティティーアイデンティティーに一意のエンティティーインスタンスがあるエンティティーインスタンスのセットです。永続コンテキスト内では、エンティティーインスタンスとそのライフサイクルは特定のエンティティーマネージャーによって管理されます。このコンテキストの範囲は、トランザクションまたは作業の拡張単位のいずれかになります。
永続ユニット
指定のエンティティーマネージャーで管理できるエンティティータイプのセットは永続ユニットによって定義されます。永続ユニットは、アプリケーションに関連する、またはアプリケーションによってグループ化されるすべてのクラスのセットを定義します。これらのクラスは、単一データストアへのマッピングに共存する必要があります。
コンテナー管理のエンティティーマネージャ-
コンテナーがライフサイクルを管理するエンティティーマネージャー。
例: アプリケーション管理のエンティティーマネージャー
ライフサイクルがアプリケーションによって管理されているエンティティーマネージャー。
Jakarta Transactions エンティティーマネージャー
Jakarta Transactions トランザクションに関連するエンティティーマネージャー。
Resource-local エンティティーマネージャー
リソーストランザクションを使用するエンティティーマネージャー (Jakarta Transactions トランザクションではない)。

その他のリソース

第2章 Hibernate の設定

2.1. Hibernate の設定

アプリケーションサーバーとスタンドアロンアプリケーションの両方のエンティティーマネージャーの設定は永続アーカイブにあります。永続アーカイブは、META-INF/ フォルダーにある persistence.xml ファイルを定義する必要がある JAR ファイルです。

persistence.xml ファイルを使用してデータベースに接続できます。これには、以下の方法があります。

  • JBoss EAP の datasources サブシステムで設定されたデータソースを指定します。

    jta-data-source は、この永続ユニットマップ先となるデータソースの Java Naming and Directory Interface 名を参照します。ここでの java:jboss/datasources/ExampleDS は、JBoss EAP に埋め込まれた H2 DB を指しています。

    persistence.xml ファイルの object-logical -mapping の例

    <persistence>
       <persistence-unit name="myapp">
          <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
          <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
          <properties>
             ... ...
          </properties>
       </persistence-unit>
    </persistence>

  • 接続プロパティーを指定して persistence.xml ファイルを明示的に設定します。

    persistence.xml ファイルで接続プロパティーを指定する例

    <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
    <property name="javax.persistence.jdbc.user" value="sa"/>
    <property name="javax.persistence.jdbc.password" value=""/>
    <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:."/>

    接続プロパティーの完全なリストは、 persistence.xml の Connection Properties Configurable を参照してください。

ランタイム時に Hibernate の動作を制御するプロパティーは複数あります。すべてはオプションで、適切なデフォルト値を持ちます。これらの Hibernate プロパティーはすべて persistence.xml で使用されます。設定可能な Hibernate プロパティーの完全リストは、Hibernate Properties を参照してください。

2.2. 2 次キャッシュ

2.2.1. 2 次キャッシュ

2 次キャッシュとは、アプリケーションセッション外部で永続化された情報を保持するローカルデータストアのことです。このキャッシュは永続プロバイダーにより管理され、アプリケーションとデータを分離することでランタイムを改善します。

JBoss EAP では、以下の目的のためにキャッシュがサポートされます。

  • Web セッションのクラスタリング
  • ステートフルセッション Bean のクラスタリング
  • SSO クラスタリング
  • Hibernate 2 次キャッシュ
  • Jakarta Persistence 2 次キャッシュ
警告

各キャッシュコンテナーは repl および dist キャッシュを定義します。これらのキャッシュは、ユーザーアプリケーションで直接使用しないでください。

2.2.2. Hibernate の 2 次キャッシュの設定

Hibernate の 2 次キャッシュとして機能する Infinispan の設定は、以下の 2 ついずれかの方法で実行できます。

Hibernate ネイティブアプリケーションを使用した Hibernate 用 2 次キャッシュの設定
  1. デプロイメントのクラスパスに hibernate.cfg.xml ファイルを作成します。
  2. 以下の XML を hibernate.cfg.xml ファイルに追加します。XML は <session-factory> タグ内になければなりません。

    <property name="hibernate.cache.use_second_level_cache">true</property>
    <property name="hibernate.cache.use_query_cache">true</property>
    <property name="hibernate.cache.region.factory_class">org.jboss.as.jpa.hibernate5.infinispan.InfinispanRegionFactory</property>
  3. アプリケーション内で Hibernate ネイティブ API を使用するには、以下の依存関係を MANIFEST.MF ファイルに追加する必要があります。

    Dependencies: org.infinispan,org.hibernate

第3章 Hibernate アノテーション

3.1. Hibernate アノテーション

Org.hibernate.annotations パッケージには、標準の Jakarta Persistence アノテーションの上に Hibernate によって提供されるアノテーションが含まれます。

表3.1 一般的なアノテーション

アノテーション説明

Check

クラス、プロパティー、またはコレクションレベルで定義できる任意の SQL チェック制約。

Immutable

エンティティーまたはコレクションにイミュータブルとしてマークを付けます。アノテーションがないということは、要素が変更されたことを意味します。

イミュータブルなエンティティーはアプリケーションによって更新されない可能性があります。イミュータブルなエンティティーの更新は無視されますが、例外は発生しません。

@Immutable をコレクションに配置すると、コレクションがイミュータブルな状態になり、コレクションへの追加および削除は許可されません。この場合、HibernateException が発生します。

表3.2 キャッシュエンティティー

アノテーション説明

Cache

キャッシュストラテジーをルートエンティティーまたはコレクションに追加します。

表3.3 コレクション関連のアノテーション

アノテーション説明

MapKeyType

永続マップのキーのタイプを定義します。

ManyToAny

異なるエンティティータイプを参照する ToMany 関連付けを定義します。エンティティータイプのマッチングは、メタデータの識別子コラムを使用して行われます。このようなマッピングはマージのみにする必要があります。

OrderBy

SQL 順序付け (HQL の順序ではなく) を使用してコレクションを順序付けます。

OnDelete

コレクション、アレイ、および結合されたサブクラスの削除で使用するストラテジー。現在、セカンダリーテーブルの OnDelete はサポートされていません。

Persister

カスタム永続機能を指定します。

Sort

コレクションのソート (Java レベルのソート)。

Where

コレクションのエンティティーまたはターゲットエンティティーに追加する要素。レシピは SQL で記述されます。

WhereJoinTable

コレクションジョインテーブルに追加する部分。レシピは SQL で記述されます。

表3.4 CRUD 操作のためのカスタム SQL

アノテーション説明

Loader

Hibernate デフォルトの FIND メソッドを上書きします。

SQLDelete

Hibernate デフォルトの DELETE メソッドを上書きします。

SQLDeleteAll

Hibernate のデフォルト DELETE ALL メソッドを上書きします。

SQLInsert

Hibernate のデフォルト INSERT INTO メソッドを上書きします。

SQLUpdate

Hibernate デフォルトの UPDATE メソッドを上書きします。

Subselect

イミュータブルで読み取り専用のエンティティーを指定の SQL サブ選択式にマッピングします。

Synchronization

自動フラッシュが正しく実行され、派生エンティティーに対するクエリーが古いデータを返さないようにします。大半は Subselect とともに使用されます。

表3.5 エンティティー

アノテーション説明

Cascade

関連付けにカスケードストラテジーを適用します。

Entity

標準の @Entity で定義された以外のメタデータが必要になる可能性のある追加のメタデータを追加します。

  • mutable: このエンティティーが変更可能であるかどうか
  • dynamicInsert : 動的な SQL を許可する
  • DynamicUpdate: 更新のための動的 SQL を許可する
  • selectBeforeUpdate: オブジェクトが実際に変更されたことが明らかでない場合、Hibernate が SQL UPDATE を実行しないように指定します。
  • polymorphism: エンティティーポリモーフィズムは PolymorphismType.IMPLICIT (デフォルト) または PolymorphismType.EXPLICIT のいずれか
  • optimisticLock: 楽観的ロックストラテジー (OptimisticLockType.VERSION、OptimisticLockType.NONE、OptimisticLockType.DIRTY または OptimisticLockType.ALL)

    注記

    アノテーション「Entity」は非推奨となり、今後のリリースで削除される予定です。個別の属性または値はアノテーションになります。

Polymorphism

ポリモーフィズム Hibernate のタイプを定義するために使用されます。

Proxy

特定のクラスのレイジーおよびプロキシー設定。

Table

プライマリーまたはセカンダリーのテーブルに情報を補完します。

Tables

Table の複数形のアノテーション。

Target

明示的なターゲットを定義し、反映および汎用的な解決を回避します。

Tuplizer

エンティティーまたはコンポーネントの tuplizer を定義します。

Tuplizers

エンティティーまたはコンポーネントの一連の tuplizer を定義します。

表3.6 フェッチ

アノテーション説明

BatchSize

SQL 読み込みのバッチサイズ。

FetchProfile

フェッチストラテジープロファイルを定義します。

FetchProfiles

@FetchProfile の複数形のアノテーション。

LazyGroup

エンティティー属性が同じグループに属する他のすべての属性と共にフェッチされる必要があることを指定します。エンティティー属性をレイジーに読み込むには、バイトコード拡張が必要です。デフォルトでは、すべての非コレクション属性は DEFAULT という名前のグループに読み込まれます。このアノテーションを使用すると、グループ内の属性にアクセスするときに異なる属性のグループを同時に初期化できます。

表3.7 フィルター

アノテーション説明

Filter

フィルターをエンティティーまたはコレクションのターゲットエンティティーに追加します。

FilterDef

フィルター定義。

FilterDefs

フィルター定義の配列。

FilterJoinTable

フィルターを結合テーブルコレクションに追加します。

FilterJoinTables

複数の @FilterJoinTable をコレクションに追加します。

フィルター

複数の @Filter を追加します。

ParamDef

パラメーター定義。

表3.8 プライマリーキー

アノテーション説明

Generated

このアノテーション付きプロパティーはデータベースによって生成されます。

GenericGenerator

タイプ解除された方法で、あらゆる Hibernate generator を記述するジェネレーターアノテーション。

GenericGenerators

汎用ジェネレーター定義のアレイ。

NaturalId

プロパティーがエンティティーの純粋な ID の一部であることを指定します。

Parameter

キー/値のパターン。

RowId

Hibernate の ROWID マッピング機能のサポート。

表3.9 継承

アノテーション説明

DiscriminatorFormula

ルートエンティティーに配置されるイデンティターの式。

DiscriminatorOptions

Hibernate 固有の識別子プロパティーを表示するオプションのアノテーションです。

MetaValue

指定の識別子値を対応するエンティティータイプにマッピングします。

表3.10 JP-QL/HQL クエリーのマッピング

アノテーション説明

NamedNativeQueries

NamedNativeQueries を拡張して、Hibernate NamedNativeQuery オブジェクトを保持します。

NamedNativeQuery

Hibernate 機能を使用した NamedNativeQuery の拡張

NamedQueries

NamedQuery を拡張して Hibernate NamedQuery オブジェクトを保持します。

NamedQuery

Hibernate 機能を使用して NamedQuery を拡張します。

表3.11 簡単なプロパティーのマッピング

アノテーション説明

AccessType

プロパティーアクセスタイプ。

Columns

列のアレイをサポートします。コンポーネントのユーザータイプマッピングに便利です。

ColumnTransformer

値をコラムから読み取り、コラムに書き込むために使用するカスタムの SQL 式。クエリーとともにオブジェクトの直接読み込み/保存に使用します。書き込み式には、値に対して 1 つの '?' プレースホルダーが必ず含まれている必要があります。

ColumnTransformers

@ColumnTransformer の複数のアノテーション複数のコラムがこの動作を使用している場合に便利です。

表3.12 プロパティー

アノテーション説明

Formula

大半の場所で、@Column の代わりとして使用するために使用されます。式は有効な SQL フラグメントである必要があります。

Index

データベースインデックスを定義します。

JoinFormula

大半の場所で、@JoinColumn の代わりとして使用するために使用されます。式は有効な SQL フラグメントである必要があります。

Parent

プロパティーを所有者 (通常は所有するエンティティー) へのポインターとして参照します。

Type

Hibernate タイプ。

TypeDef

Hibernate タイプ定義。

TypeDefs

Hibernate タイプ定義の配列。

表3.13 単一の関連付け関連のアノテーション

アノテーション説明

Any

複数のエンティティータイプを参照するトール関連付けを定義します。一致したエンティティータイプのマッチングは、メタデータの識別子コラムを使用して行われます。このようなマッピングはマージのみにする必要があります。

AnyMetaDef

@Any および @ManyToAny メタデータを定義します。

AnyMetaDefs

@Any および @ManyToAny のメタデータセットを定義します。エンティティーレベルまたはパッケージレベルで定義できます。

Fetch

指定の関連付けに使用されるフェッチストラテジーを定義します。

LazyCollection

コレクションのレイジーステータスを定義します。

LazyToOne

ToOne 関連づけのレイジーステータスを定義します (OneToOne または ManyToOne)。

NotFound

要素が関連上に見つからない場合に行うアクション。

表3.14 楽観的ロック

アノテーション説明

OptimisticLock

アノテーションが付けられたプロパティーの変更によってエンティティーバージョンの増分がトリガーされるかどうか。アノテーションが存在しない場合は、プロパティーが楽観的ロックストラテジーに関与します (デフォルト)。

OptimisticLocking

エンティティーに適用される楽観的ロックのスタイルを定義するために使用されます。階層では、ルートエンティティーでのみ有効です。

Source

Version および timestamp version プロパティーと併せてのオプションのアノテーションです。アノテーションの値で、タイムスタンプの生成先が決まります。

第4章 Hibernate Query 言語

4.1. Hibernate Query 言語について

Jakarta Persistence クエリー言語の概要

Jakarta Persistence クエリー言語は、Jakarta Persistence 仕様の一部として定義されるプラットフォームに依存しないオブジェクト指向のクエリー言語です。

Jakarta Persistence クエリー言語は、リレーショナルデータベースに保存されているエンティティーに対してクエリーを行うために使用されます。これは SQL に大きく影響を受けています。また、そのクエリーは構文の SQL クエリーに類似しますが、データベーステーブルと直接連携するのではなく Jakarta Persistence エンティティーオブジェクトに対して動作します。

HQL の概要

Hibernate Query Language (HQL) は、SQL と同様のパワフルなクエリー言語です。ただし、SQL と比較すると、HQL は完全にオブジェクト指向で、継承、ポリモーフィズム、関連付けなどの概念を認識します。

HQL は Jakarta Persistence クエリー言語のスーパーセットです。HQL クエリーは常に有効な Jakarta Persistence クエリー言語クエリーではありませんが、Jakarta Persistence クエリー言語のクエリーは常に有効な HQL クエリーです。

HQL および Jakarta Persistence クエリー言語は、クエリー操作を実行するタイプセーフでない方法です。条件クエリーは、クエリーにタイプセーフなアプローチを提供します。

4.2. HQL ステートメントについて

HQL および Jakarta Persistence クエリー言語は、SELECT、UPDATEおよび DELETE ステートメントの両方を許可します。さらに HQL では、SQL INSERT-SELECT と似た形式の INSERT ステートメントを使用できます。

以下の表は、さまざまな HQL ステートメントの Backus-Naur Form (BNF) 表記の構文を示しています。

表4.1 HQL ステートメント

ステートメント説明

SELECT

HQL における SELECT ステートメントの BNF は以下のとおりです。

select_statement :: =
        [select_clause]
        from_clause
        [where_clause]
        [groupby_clause]
        [having_clause]
        [orderby_clause]

UPDATE

HQL の UPDATE ステートメントの BNF は、Jakarta Persistence クエリー言語と同じになります。

update_statement ::= update_clause [where_clause]

update_clause ::= UPDATE entity_name [[AS] identification_variable]
        SET update_item {, update_item}*

update_item ::= [identification_variable.]{state_field | single_valued_object_field}
        = new_value

new_value ::= scalar_expression |
                simple_entity_expression |
                NULL

DELETE

HQL の DELETE ステートメントの BNF は、Jakarta Persistence クエリー言語と同じになります。

delete_statement ::= delete_clause [where_clause]

delete_clause ::= DELETE FROM entity_name [[AS] identification_variable]

INSERT

HQL の INSERT ステートメントの BNF は以下の通りです。

insert_statement ::= insert_clause select_statement

insert_clause ::= INSERT INTO entity_name (attribute_list)

attribute_list ::= state_field[, state_field ]*

これと同等の Jakarta Persistence クエリー言語はありません。

警告

Hibernate では、DML (Data Manipulation Language) を使用して、HQL (Hibernate Query Language) を介して、マップされたデータベースにへのデータの直接挿入、更新、および削除を一括で行うことができます。

複数のオブジェクトまたは関係マッピングに違反し、オブジェクト状態に影響を与える可能性があります。オブジェクト状態は、基盤のデータベースで実行される操作によって、メモリー内オブジェクトの状態が影響を受けることはありません。インメモリーデータは、インメモリーデータが使用される場合は注意して使用する必要があります。

UPDATE ステートメントおよび DELETE ステートメント

UPDATE ステートメントおよび DELETE ステートメントの擬似構文は次のとおりです。

( UPDATE | DELETE ) FROM?EntityName (WHERE where_conditions)?.

注記

FROM キーワードおよび WHERE Clause はオプションです。FROM 句は、残りのクエリーで使用できるオブジェクトモデルタイプのスコープを定義します。また、残りのクエリーで使用できるすべての識別変数も定義します。WHERE 句では、返されるインスタンスの一覧を絞り込むことができます。

UPDATE ステートメントまたは DELETE ステートメントの実行結果は、実際に影響を受ける (更新または削除される) 行数です。

例: 一括更新ステートメント

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlUpdate = "update Company set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
        .setString( "newName", newName )
        .setString( "oldName", oldName )
        .executeUpdate();
tx.commit();
session.close();

例: 一括削除ステートメント

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlDelete = "delete Company where name = :oldName";
int deletedEntities = s.createQuery( hqlDelete )
        .setString( "oldName", oldName )
        .executeUpdate();
tx.commit();
session.close();

Query.executeUpdate() メソッドによって返される int 値は、オペレーションの影響を受けた、データベース内のエンティティーの数を示します。

内部では、複数の SQL ステートメントを使用して、DML Update または Delete 更新リクエストまたは削除リクエストに応答して操作を実行する場合があります。これは、テーブルと、更新または削除が必要な結合テーブルの間に存在する関係が原因です。

たとえば、上記の例のように delete ステートメントを実行すると、oldName という名前の企業用の Company テーブルだけでなく、結合したテーブルに対しても削除が実行されます。したがって、Employee テーブルと多対多関係の双方向の Company テーブルは、前回の例の実行に成功すると、一致する結合テーブル Company_Employee から行を失います。

上記の deletedEntries 値には、この操作によって影響を受けるすべての行の数 (結合テーブルの行を含む) が含まれます。

重要

一括更新や削除の操作の実行時には、アクティブな永続コンテキストでデータベースとエンティティー間で不整合が生じる可能性があるため注意が必要です。一般的に、一括更新および削除操作は、新しい永続コンテキストのトランザクション内で、またはこのような操作の影響を受ける可能性のある状態を持つエンティティーをフェッチまたはアクセスする前にのみ実行する必要があります。

INSERT ステートメントについて

HQL は、INSERT ステートメントを定義する機能を追加します。これと同等の Jakarta Persistence クエリー言語はありません。HQL INSERT ステートメントの Backus-Naur Form (BNF) は以下の通りです。

insert_statement ::= insert_clause select_statement

insert_clause ::= INSERT INTO entity_name (attribute_list)

attribute_list ::= state_field[, state_field ]*

tribute_list は、SQL INSERT ステートメントのコラム指定に似ています。マッピングされた継承に関連するエンティティーでは、名前付きエンティティーに直接定義された属性のみが attribute_list で使用できます。スーパークラスプロパティーは許可されておらず、サブクラスプロパティーは意味を成しません。つまり、INSERT ステートメントは本質的にはポリモーフィックではありません。

警告

select_statement には、有効な HQL 選択クエリーを使用できます。この場合、戻り値のタイプは挿入で想定されるタイプと一致する必要があります。現在、これは、チェックによるデータベースへの再参照を許可するのではなく、クエリーのコンパイル時に確認されます。これにより、Hibernate Types が equal とは逆に equivalent であるため、問題が発生する可能性があります。たとえば、これにより、データベースが区別を行わなかったり、変換を処理できない場合でも、org.hibernate.type.DateType としてマップされた属性と org.hibernate.type.TimestampType として定義された属性間で不一致の問題が発生する可能性があります。

id 属性には、insert ステートメントに 2 つのオプションを付与します。attribute_listid プロパティーを明示的に指定することができます。この場合、その値は、対応する select 式から取得されるか、または生成された値が使用される場合は attribute_list から省略されます。後者のオプションは、データベースで (in the database) で動作する ID ジェネレーターを使用している場合にのみ利用できます。メモリー内 (in memory) タイプジェネレーターでこのオプションを使用しようとすると、解析中に例外が発生します。

ロック属性の場合、insert ステートメントでは、以下のいずれかのオプションが再度提供されます。attribute_list に属性を指定できます。この場合、その値は対応する選択式から取得されます。あるいは、attribute_list から除外できます。その場合は、対応する org.hibernate.type.VersionType で定義される seed value が使用されます。

例: INSERT Query ステートメント

String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery(hqlInsert).executeUpdate();

例: Bulk Insert ステートメント

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlInsert = "insert into Account (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery( hqlInsert )
        .executeUpdate();
tx.commit();
session.close();

SELECT ステートメントを使用して id 属性の値を指定しない場合、基礎となるデータベースが自動生成キーをサポートする限り、識別子が生成されます。この一括挿入操作の戻り値は、データベースで実際に作成されたエントリー数です。

4.3. HQL の順序について

クエリーの結果を順序付けすることもできます。ORDER BY は、結果の順序付けに使用される選択した値を指定するために使用されます。順序単位で有効とみなされる式のタイプには、以下が含まれます。

  • ステートフィールド
  • コンポーネント/組み込み可能な属性
  • 算術演算、関数などのスカラー式。
  • 前の式タイプに対して select 句で宣言された識別変数。

HQL は、order-by 句で参照されるすべての値が select 句内で命名されることを必須としませんが、Jakarta Persistence クエリー言語で必要になります。データベースの移植性を求めるアプリケーションは、すべてのデータベースが、選択節で参照されていない order-by 句での参照値に対応しているわけではないことに注意してください。

order-by の個々の式は、必要な順序を示すために ASC (昇順) または DESC (下記) で修飾できます。

例: Order By

// legal because p.name is implicitly part of p
select p
from Person p
order by p.name

select c.id, sum( o.total ) as t
from Order o
    inner join o.customer c
group by c.id
order by t

4.4. コレクションメンバーの参照について

コレクション値の関連付けへの参照は、実際にはそのコレクションのを参照します。

例: コレクション参照

select c
from Customer c
    join c.orders o
    join o.lineItems l
    join l.product p
where o.status = 'pending'
  and p.status = 'backorder'

// alternate syntax
select c
from Customer c,
    in(c.orders) o,
    in(o.lineItems) l
    join l.product p
where o.status = 'pending'
  and p.status = 'backorder'

この例では、識別変数 o は実際には、Customer#orders 関連付けの要素タイプであるオブジェクトモデルタイプ Order を参照します。

この例では、IN 構文を使用してコレクションの関連付けジョインを指定する代替構文も示しています。両方の形式は同じです。アプリケーションの選択を選択するのは、単に好みの問題です。

4.5. 修飾パス式について

これまでは、コレクション値関連づけは、コレクションのを実際に参照していると言及されました。コレクションのタイプによっては、明示的な修飾式のセットも利用できます。

表4.2 修飾パス式

説明

VALUE

コレクション値を参照します。修飾子を指定しないのと同じです。意図を明示的に表示するのに役立ちます。いずれかのタイプのコレクションと値の参照に有効です。

INDEX

HQL ルールによると、これは、javax.persistence.OrderColumn アノテーションを指定して Map キーまたは List の場所 (別名 OrderColumn 値) を参照する Maps と List の両方に対して有効です。ただし、Jakarta Persistence クエリー言語は、これを List ケースで使用するために予約し、MAP ケースに KEY を追加します。Jakarta Persistence プロバイダーの移植性に関心のあるアプリケーションは、この区別を認識する必要があります。

KEY

Maps にのみ有効です。マップのキーを参照します。キー自体がエンティティーである場合は、さらに移動することができます。

ENTRY

Maps にのみ有効です。Map の論理 java.util.Map.Entry タプル (キーと値の組み合わせ) を参照します。ENTRY はターミナルパスとしてのみ有効で、選択でのみ有効です。

例: 修飾コレクション参照

// Product.images is a Map<String,String> : key = a name, value = file path

// select all the image file paths (the map value) for Product#123
select i
from Product p
    join p.images i
where p.id = 123

// same as above
select value(i)
from Product p
    join p.images i
where p.id = 123

// select all the image names (the map key) for Product#123
select key(i)
from Product p
    join p.images i
where p.id = 123

// select all the image names and file paths (the 'Map.Entry') for Product#123
select entry(i)
from Product p
    join p.images i
where p.id = 123

// total the value of the initial line items for all orders for a customer
select sum( li.amount )
from Customer c
        join c.orders o
        join o.lineItems li
where c.id = 123
  and index(li) = 1

4.6. HQL 関数について

HQL は、使用中の基盤のデータベースに関係なく利用可能な標準の関数を定義します。HQL は、ダイアレクトおよびアプリケーションで定義される追加の機能を理解することもできます。

4.6.1. HQL の標準化機能

以下の関数は、使用中の基盤のデータベースに関係なく HQL で利用できます。

表4.3 HQL の標準化機能

関数説明

BIT_LENGTH

バイナリーデータの長さを返します。

CAST

SQL キャストを実行します。cast ターゲットは、使用する Hibernate マッピングタイプに名前を付ける必要があります。

EXTRACT

Datetime 値に対して SQL の抽出を実行します。展開により、年などの日付/ 時間値の一部が返されます。以下の省略形式を参照してください。

SECOND

2 つ目を抽出するための省略された抽出形式。

MINUTE

分を抽出するための省略された抽出形式。

HOUR

時を抽出するための省略された抽出形式。

DAY

日を抽出するための省略された抽出形式。

MONTH

月を抽出するための省略された抽出形式。

YEAR

年を抽出するための省略された抽出形式。

STR

値を文字データとしてキャストするための省略形式。

4.6.2. HQL 非標準化機能

Hibernate ダイアレクトは、その特定のデータベース製品で利用できると認識されている追加の関数を登録できます。これらは、そのデータベースまたはダイアレクトを使用する場合にのみ利用できます。データベースの移植性を目的とするアプリケーションは、このカテゴリーで関数を使用することを避ける必要があります。

アプリケーション開発者は、独自の機能のセットも提供します。これは、通常は、カスタムの SQL 関数、または SQL のスニペットのエイリアスを表します。このような関数宣言は、org.hibernate.cfg.ConfigurationaddSqlFunction メソッドを使用して作成されます。

4.6.3. 連結操作

HQL は、連結 (CONCAT) 関数のサポートのほかに連結演算子を定義します。これは Jakarta Persistence クエリー言語では定義されないため、移植可能なアプリケーションは使用しないようにしてください。連結演算子は、SQL 連結演算子 (||) から取得されます。

例: 連結操作の例

select 'Mr. ' || c.name.first || ' ' || c.name.last
from Customer c
where c.gender = Gender.MALE

4.7. 動的インスタンス化について

select 句でのみ有効な特定の式タイプがあります。Hibernate では、これを「動的なインスタンス化 (dynamic instantiation)」と呼びます。Jakarta Persistence クエリー言語はこの機能の一部をサポートし、これを「コンストラクター式」と呼びます。

例: 動的インスタンス化の例 - コンストラクター

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

ここで Object[] を扱うのではなく、クエリーの結果として返されるタイプセーフな Java オブジェクトの値をラップします。クラス参照は完全修飾する必要があり、一致するコンストラクターが必要です。

ここでクラスをマッピングする必要はありません。エンティティーを表す場合、生成されるインスタンスは NEW 状態 (管理されない) で返されます。

これは、Jakarta Persistence クエリー言語もサポートします。HQL は、追加の「動的なインスタンス化」機能に対応しています。まず、クエリーはスカラー結果に対して Object[] ではなく 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

このクエリーの結果は List<Object[]> ではなく List<List> になります。

HQL は、マップでのスカラー結果のラッピングもサポートします。

例: 動的インスタンス化の例 - マップ

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

select new map( max(c.bodyWeight) as max, min(c.bodyWeight) as min, count(*) as n )
from Cat cxt

このクエリーの結果は List<Object[]> ではなく List<Map<String,Object>> になります。マップのキーは、選択式に対して提供されたエイリアスによって定義されます。

4.8. HQL 述語について

述語は、where 句、having 句、検索 CASE 式の基礎を形成します。これらは式であり、通常は TRUE または FALSE に解決されます。ただし、NULL 値が関係するブール値比較は一般的に UNKNOWN に解決します。

HQL の述語

  • Null 述語

    Null の値を確認します。基本的な属性参照、エンティティーの参照、およびパラメーターに適用できます。さらに HQL を使用すると、コンポーネント/ 組み込み可能なタイプに適用できます。

    例: NULL チェック

    // select everyone with an associated address
    select p
    from Person p
    where p.address is not null
    
    // select everyone without an associated address
    select p
    from Person p
      where p.address is null

  • 述語と同様

    文字列値に対して、同様の比較を実行します。構文は以下のとおりです。

    like_expression ::=
           string_expression
           [NOT] LIKE pattern_value
           [ESCAPE escape_character]

    セマンティクスは、式のような SQL のことに従います。paattern_value は、string_expression で一致を試みるパターンです。SQL と同様に、pattern_value はワイルドカードに _ (アンダースコア) および % (パーセント) を使用できます。意味は同じです。_ は、単一の文字に一致します。% は任意の数の文字に一致します。

    オプションの escape_character は、pattern_value_% の特別な意味をエスケープするために使用されるエスケープ文字を指定するために使用されます。これは、_ または % のいずれかを含むパターンを検索する必要がある場合に便利です。

    例: LIKE 述語

    select p
    from Person p
    where p.name like '%Schmidt'
    
    select p
    from Person p
    where p.name not like 'Jingleheimmer%'
    
    // find any with name starting with "sp_"
    select sp
    from StoredProcedureMetadata sp
    where sp.name like 'sp|_%' escape '|'

  • BETWEEN 演算子

    SQL BETWEEN 式と同様です。値が 2 つの他の値の範囲内にあるかどうかの評価を実行します。すべてのオペランドは、同等の型を持つ必要があります。

    例: BETWEEN 演算子

    select p
    from Customer c
        join c.paymentHistory p
    where c.id = 123
      and index(p) between 0 and 9
    
    select c
    from Customer c
    where c.president.dateOfBirth
            between {d '1945-01-01'}
                and {d '1965-01-01'}
    
    select o
    from Order o
    where o.total between 500 and 5000
    
    select p
    from Person p
    where p.name between 'A' and 'E'

  • IN 述語

    IN 述語は、特定の値が値の一覧にあることを確認します。構文は次のとおりです。

    in_expression ::= single_valued_expression
                [NOT] IN single_valued_list
    
    single_valued_list ::= constructor_expression |
                (subquery) |
                collection_valued_input_parameter
    
    constructor_expression ::= (expression[, expression]*)

    single_valued_expression のタイプと single_valued_list の個別の値は一致している必要があります。Jakarta Persistence クエリー言語は、ここで有効なタイプを string、数値、日付、時間、タイムスタンプ、および列挙タイプに制限します。Jakarta Persistence クエリー言語では、single_valued_expression は以下のみを参照できます。

    • 「状態フィールド」(state fields) は、単純な属性の用語です。具体的には、関連付けおよびコンポーネント/組み込み属性が除外されます。
    • エンティティー型式。

      HQL では、single_valued_expression はより幅広い式タイプを参照することができます。1 価の関連づけが許可されています。コンポーネント/組み込み属性も同様です。ただし、この機能は基盤のデータベースのタプルのサポートレベルまたは「ロー値のコンストラクター構文」 (row value constructor syntax) によって異なります。さらに、HQL では値のタイプは制限されませんが、アプリケーション開発者は、基盤のデータベースベンダーに基づいてサポートが制限される可能性があることに注意する必要があります。これは、Jakarta Persistence クエリー言語の制限の主な理由です。

      値の一覧は多数の異なるソースから取得できます。constructor_expression およびcollection_valued_input_parameter では、値の一覧は空にすることはできません。少なくとも 1 つの値が含まれている必要があります。

      例: IN 述語

      select p
      from Payment p
      where type(p) in (CreditCardPayment, WireTransferPayment)
      
      select c
      from Customer c
      where c.hqAddress.state in ('TX', 'OK', 'LA', 'NM')
      
      select c
      from Customer c
      where c.hqAddress.state in ?
      
      select c
      from Customer c
      where c.hqAddress.state in (
          select dm.state
          from DeliveryMetadata dm
          where dm.salesTax is not null
      )
      
      // Not Jakarta Persistence query language compliant!
      select c
      from Customer c
      where c.name in (
          ('John','Doe'),
          ('Jane','Doe')
      )
      
      // Not Jakarta Persistence query language compliant!
      select c
      from Customer c
      where c.chiefExecutive in (
          select p
          from Person p
          where ...
      )

4.9. 関連比較について

比較には、等号の =、>、>=、<、⇐、<> のいずれかが関係します。HQL は、<> と比べる比較演算子として != も定義します。オペランドは同じタイプである必要があります。

例: 比較例

// numeric comparison
select c
from Customer c
where c.chiefExecutive.age < 30

// string comparison
select c
from Customer c
where c.name = 'Acme'

// datetime comparison
select c
from Customer c
where c.inceptionDate < {d '2000-01-01'}

// enum comparison
select c
from Customer c
where c.chiefExecutive.gender = com.acme.Gender.MALE

// boolean comparison
select c
from Customer c
where c.sendEmail = true

// entity type comparison
select p
from Payment p
where type(p) = WireTransferPayment

// entity value comparison
select c
from Customer c
where c.chiefExecutive = c.chiefTechnologist

また、比較には ALLANYSOME などの修飾子を含めることもできます。some および ANY は同義語です。

ALL 修飾子は、サブくエリーの結果のすべての値に対して比較が true の場合に true に解決します。これは、値が空の場合は false に解決します。

例: すべてのサブクエリー比較修飾子の例

// select all players that scored at least 3 points
// in every game.
select p
from Player p
where 3 > all (
   select spg.points
   from StatsPerGame spg
   where spg.player = p
)

ANY/SOME 修飾子は、サブクエリーの結果の値いずれかの比較が true の場合に true に解決します。これは、値が空の場合は false に解決します。

4.10. バイトコードの機能強化

4.10.1. Lazy 属性の読み込み

Lazy 属性の読み込みはバイトコードの拡張機能です。これにより、データベースからフェッチする際にエンティティーの特定の部分のみがロードされ、残りの部分もロードする必要があることを Hibernate に指示できます。これは、エンティティーの状態が必要に応じて一度に読み込まれるエンティティーを中心とするレイジーロードのプロキシーベースの概念とは異なります。バイトコード拡張では、必要に応じて個別の属性または属性グループが読み込まれます。

レイジー属性は一緒にロードするように指定できます。これは lazy group と呼ばれます。デフォルトでは、すべての単数属性が単一のグループに含まれます。あるレイジーな singular 属性にアクセスすると、レイジーなすべての singular 属性が読み込まれます。レイジー singular グループに反して、レイジーな複数の属性はそれぞれ個別のレイジーグループです。この動作は、@org.hibernate.annotations.LazyGroup アノテーションで明示的に制御できます。

@Entity
public class Customer {

    @Id
    private Integer id;

    private String name;

    @Basic( fetch = FetchType.LAZY )
    private UUID accountsPayableXrefId;

    @Lob
    @Basic( fetch = FetchType.LAZY )
    @LazyGroup( "lobs" )
    private Blob image;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public UUID getAccountsPayableXrefId() {
        return accountsPayableXrefId;
    }

    public void setAccountsPayableXrefId(UUID accountsPayableXrefId) {
        this.accountsPayableXrefId = accountsPayableXrefId;
    }

    public Blob getImage() {
        return image;
    }

    public void setImage(Blob image) {
        this.image = image;
    }
}

上記の例では、accountsPayableXrefIdimage の 2 つのレイジー属性があります。これらの各属性は、異なるフェッチグループの一部です。accountsPayableXrefId 属性はデフォルトのフェッチグループの一部です。accountsPayableXrefId へのアクセスは、image 属性の読み込みを強制しません (逆の場合もまた然り)。

第5章 Hibernate サービス

5.1. Hibernate サービスについて

サービスは、Hibernate を提供するクラスで、さまざまなタイプの機能のプラグ可能な実装を提供します。特に、特定のサービスコントラクトインターフェースの実装です。このインターフェースはサービスロールとして知られています。実装クラスはサービス実装として知られています。一般的に、ユーザーはすべての標準サービスロール (上書き) の代替の実装をプラグインできます。また、サービスロールのベースセット (拡張) 以外に追加のサービスを定義することもできます。

5.2. サービス契約について

サービスの基本的な要件は、org.hibernate.service.Service のマーカーインターフェースを実装することです。Hibernate は、基本的なタイプの安全のためにこの内部で使用します。

オプションとして、サービスは org.hibernate.service.spi.Startable および org.hibernate.service.spi.Stoppable インターフェースを実装し、開始および停止の通知を受信することもできます。別のオプションのサービスコントラクトは org.hibernate.service.spi.Manageable で、Jakaarta Management 統合が有効になっていると、Jakarta Management でサービスが管理可能であるとマークされます。

5.3. サービス依存関係の種類

サービスは、以下の方法のいずれかを使用して他のサービスの依存関係を宣言できます。

@org.hibernate.service.spi.InjectService

単一のパラメーターを受け入れ、@InjectService でアノテーションが付けられたサービス実装クラスのメソッドは 、別のサービスの挿入を要求していると見なされます。

デフォルトでは、method パラメーターのタイプは、インジェクトされるサービスロールになることが想定されます。パラメーターのタイプがサービスロールと異なる場合は、InjectServiceserviceRole 属性を使用してロールに明示的な名前を付ける必要があります。

デフォルトでは、インジェクトされたサービスは必須とみなされ、名前付き依存サービスがないと、起動に失敗します。インジェクトされるサービスがオプションの場合、InjectService の必要な属性はfalse として宣言される必要があります。デフォルトは true です。

org.hibernate.service.spi.ServiceRegistryAwareService

次のアプローチは、単一の injectServices メソッドを宣言する、オプションのサービスインターフェース org.hibernate.service.spi.ServiceRegistryAwareService をサービスが実装するプルアプローチです。

Hibernate は起動時に、org.hibernate.service.ServiceRegistry 自体をこのインターフェースを実装するサービスに挿入します。その後、ServiceRegistry 参照を使用して必要な追加サービスを見つけることができます。

5.3.1. サービスレジストリー

5.3.1.1. ServiceRegistry について

中央のサービス API はサービス自体以外に、org.hibernate.service.ServiceRegistry インターフェースです。サービスレジストリーの主な目的は、サービスへのアクセスを保持し、管理し、提供することです。

サービスレジストリーは階層的です。あるレジストリーのサービスは、同じレジストリーのサービスや任意の親レジストリーに依存して使用できます。

org.hibernate.service.ServiceRegistryBuilder を使用して org.hibernate.service.ServiceRegistry インスタンスをビルドします。

ServiceRegistryBuilder を使用した ServiceRegistry の作成例

ServiceRegistryBuilder registryBuilder =
    new ServiceRegistryBuilder( bootstrapServiceRegistry );
    ServiceRegistry serviceRegistry = registryBuilder.buildServiceRegistry();

5.3.2. カスタムサービス

5.3.2.1. カスタムサービスについて

org.hibernate.service.ServiceRegistry を構築すると、不変とみなされます。このサービス自体は再設定を受け入れる可能性がありますが、ここでの不変性はサービスの追加または置き換えを意味します。そのため、org.hibernate.service.ServiceRegistryBuilder で利用できる別のロールは、これから生成される org.hibernate.service.ServiceRegistry に含まれるサービスの調整を許可することです。

カスタムサービスについて org.hibernate.service.ServiceRegistryBuilder に指示する方法は 2 つあります。

  • org.hibernate.service.spi.BasicServiceInitiator クラスを実装し、サービスクラスのオンデマンド構築を制御し、addInitiator メソッドを使用して org.hibernate.service.ServiceRegistryBuilder に追加します。
  • サービスクラスをインスタンス化し、addService メソッドを使用して、org.hibernate.service.ServiceRegistryBuilder に追加します。

新規サービスロールの追加やサービス実装の置き換えなどサービスの上書きなど、レジストリーの拡張にはいずれかのアプローチが有効です。

例: ServiceRegistryBuilder を使用して、既存のサービスをカスタムサービスに置き換える

ServiceRegistryBuilder registryBuilder =
    new ServiceRegistryBuilder(bootstrapServiceRegistry);
registryBuilder.addService(JdbcServices.class, new MyCustomJdbcService());
ServiceRegistry serviceRegistry = registryBuilder.buildServiceRegistry();

public class MyCustomJdbcService implements JdbcServices{

   @Override
   public ConnectionProvider getConnectionProvider() {
       return null;
   }

   @Override
   public Dialect getDialect() {
       return null;
   }

   @Override
   public SqlStatementLogger getSqlStatementLogger() {
       return null;
   }

   @Override
   public SqlExceptionHelper getSqlExceptionHelper() {
       return null;
   }

   @Override
   public ExtractedDatabaseMetaData getExtractedMetaDataSupport() {
       return null;
   }

   @Override
   public LobCreator getLobCreator(LobCreationContext lobCreationContext) {
       return null;
   }

   @Override
   public ResultSetWrapper getResultSetWrapper() {
       return null;
   }
}

5.3.3. Boot-Strap レジストリー

5.3.3.1. Boot-strap レジストリーについて

boot-strap レジストリーは、ほとんどの機能を機能させるために絶対に利用できるようにする必要のあるサービスを保持します。ここでの主要なサービスは、ClassLoaderService です。これは最適な例です。設定ファイルを解決する場合でも、クラスローディングサービス (例: リソース検索) へのアクセスが必要になります。これは、通常の使用時に親ではなく、ルートレジストリーです。

boot-strap レジストリーのインスタンスは、org.hibernate.service.BootstrapServiceRegistryBuilder クラスを使用して作成されます。

BootstrapServiceRegistryBuilder の使用

例: BootstrapServiceRegistryBuilder の使用

BootstrapServiceRegistry bootstrapServiceRegistry =
    new BootstrapServiceRegistryBuilder()
    // pass in org.hibernate.integrator.spi.Integrator instances which are not
    // auto-discovered (for whatever reason) but which should be included
    .with(anExplicitIntegrator)
    // pass in a class loader that Hibernate should use to load application classes
    .with(anExplicitClassLoaderForApplicationClasses)
    // pass in a class loader that Hibernate should use to load resources
    .with(anExplicitClassLoaderForResources)
    // see BootstrapServiceRegistryBuilder for rest of available methods
    ...
    // finally, build the bootstrap registry with all the above options
    .build();

5.3.3.2. BootstrapRegistry サービス

org.hibernate.service.classloading.spi.ClassLoaderService

Hibernate はクラスローダーと対話する必要があります。ただし、Hibernate または任意のライブラリーと対話する方法は、アプリケーションをホストしているランタイム環境によって異なります。アプリケーションサーバー、OSGi コンテナー、およびその他のモジュラークラスローディングシステムでは、非常に特殊なクラスローディング要件が課せられています。このサービスは、この環境的な複雑性からの抽象化を Hibernate に提供します。また、同様に重要な点として、単一スワップ可能なコンポーネントでこれを実行します。

クラスローダーとの対話では、Hibernate には以下の機能が必要になります。

  • アプリケーションクラスを検索する機能
  • インテグレーションクラスを検索する機能
  • プロパティーファイルや XML ファイルなどのリソースを検索する機能
  • java.util.ServiceLoader をロードする機能

    注記

    現在、アプリケーションクラスをロードする機能と、統合クラスをロードする機能が、サービス上の単一の load class 機能に統合されています。これは、今後のリリースで変更される可能性があります。

org.hibernate.integrator.spi.IntegratorService

アプリケーション、アドオン、およびその他のモジュールは Hibernate と統合する必要があります。前述の方法では、各モジュールの登録を調整するために、通常アプリケーションなどのコンポーネントが必要でした。この登録は、各モジュールのインテグレーターに代わって実施されました。

このサービスは、検出機能に重点を置いています。org.hibernate. integrator .spi.Integrator コントラクトの実装を検出するために、org.hibernate.service.classloading.spi.ClassLoaderService が提供する標準の java.util.ServiceLoader 機能を利用 します。

インテグレーターは、単に /META-INF/services/org.hibernate.integrator.spi.Integrator という名前のファイルを定義し、これをクラスパスで利用できるようにします。

このファイルは、java.util.ServiceLoader メカニズムによって使用されます。これは、1 行ずつ org.hibernate.integrator.spi.Integrator インターフェースを実装するクラスの完全修飾名を一覧表示します。

5.3.4. SessionFactory レジストリー

すべてのレジストリータイプのインスタンスを指定の org.hibernate.SessionFactory のターゲットとして扱うのがベストプラクティスですが、このグループのサービスのインスタンスは単一の org.hibernate.SessionFactory に明示的に所属します。

相違点は、開始タイミングに関する事項です。通常、org.hibernate.SessionFactory にアクセスするにはアクセスが必要になります。この特別なレジストリーは org.hibernate.service.spi.SessionFactoryServiceRegistry です。

5.3.4.1. SessionFactory サービス

org.hibernate.event.service.spi.EventListenerRegistry

説明
イベントリスナーを管理するためのサービスです。
イニシエーター
org.hibernate.event.service.internal.EventListenerServiceInitiator
実装
org.hibernate.event.service.internal.EventListenerRegistryImpl

5.3.5. インテグレーター

org.hibernate.integrator.spi.Integrator は、開発者が機能している SessionFactory をビルドするプロセスにフックできるようにする簡単な方法を提供することを目的としています。org.hibernate.integrator.spi.Integrator インターフェースは関連する以下のメソッドを定義します。

  • integrate では、ビルドプロセスへのフックが可能になります。
  • disintegrate では、SessionFactory をシャットダウンできます。
注記

統合のオーバーロード形式である org.hibernate.integrator.spi.Integrator で定義されている 3 つ目のメソッドがあります。これは、org.hibernate.cfg.Configuration ではなく、org.hibernate.metamodel.source.MetadataImplementor を受け入れます。

IntegratorService で利用できる検出アプローチに加え、BootstrapServiceRegistry のビルド時にアプリケーションが手動でインテグレーター実装を登録できます。

5.3.5.1. インテグレーターのユースケース

org.hibernate.integrator.spi.Integrator の主なユースケースは、イベントリスナーを登録し、サービスを提供します。org.hibernate.integrator.spi.ServiceContributingIntegratorを参照してください。

例: イベントリスナーの登録

public class MyIntegrator implements org.hibernate.integrator.spi.Integrator {

    public void integrate(
            Configuration configuration,
            SessionFactoryImplementor sessionFactory,
            SessionFactoryServiceRegistry serviceRegistry) {
        // As you might expect, an EventListenerRegistry is the thing with which event listeners are registered  It is a
        // service so we look it up using the service registry
        final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService(EventListenerRegistry.class);

        // If you wish to have custom determination and handling of "duplicate" listeners, you would have to add an
        // implementation of the org.hibernate.event.service.spi.DuplicationStrategy contract like this
        eventListenerRegistry.addDuplicationStrategy(myDuplicationStrategy);

        // EventListenerRegistry defines 3 ways to register listeners:
        //     1) This form overrides any existing registrations with
        eventListenerRegistry.setListeners(EventType.AUTO_FLUSH, myCompleteSetOfListeners);
        //     2) This form adds the specified listener(s) to the beginning of the listener chain
        eventListenerRegistry.prependListeners(EventType.AUTO_FLUSH, myListenersToBeCalledFirst);
        //     3) This form adds the specified listener(s) to the end of the listener chain
        eventListenerRegistry.appendListeners(EventType.AUTO_FLUSH, myListenersToBeCalledLast);
    }
}

第6章 Hibernate Envers

6.1. Hibernate Envers について

Hibernate Enver は監査およびバージョン管理システムであり、JBoss EAP に永続クラスへのこれまでの変更を追跡する手段を提供します。監査テーブルは @Audited アノテーションが付けられたエンティティーに対して作成されています。これは、エンティティーに加えられた変更の履歴が保存されます。その後、データを取得し、クエリーできます。

Envers では、開発者は以下を行うことができます。

  • Jakarta Persistence 仕様によって定義されたすべてのマッピングの監査
  • Jakarta Persistence 仕様を拡張するすべての hibernate マッピングの監査
  • ネイティブ Hibernate API を使用する、または、これによってマッピングされるエンティティーの監査
  • リビジョンエンティティーを使用した各リビジョンのデータのログ記録
  • 履歴データのクエリー

6.2. 永続クラスの監査について

永続クラスの監査は、Hibernate 環境と @Audited アノテーションで JBoss EAP で実行されます。アノテーションがクラスに適用されると、エンティティーの改訂履歴を保存するテーブルが作成されます。

クラスに変更が行われるたびに、エントリーが監査テーブルに追加されます。エントリーにはクラスへの変更が含まれ、リビジョン番号が指定されます。これは、変更をロールバックしたり、以前のリビジョンを表示したりできることを意味します。

6.3. 監査ストラテジー

6.3.1. 監査ストラテジーについて

監査ストラテジーは、監査情報の永続化、クエリー、および保存方法を定義します。Hibernate Evers には現在、以下の 2 つの監査ストラテジーがあります。

デフォルトの監査ストラテジー
  • このストラテジーは、開始リビジョンとともに監査データの保存を永続化します。監査されたテーブルで挿入、更新、削除される行ごとに、有効性の開始リビジョンとともに、監査テーブルに 1 つ以上の行を挿入します。
  • 監査テーブルの行は、挿入後には更新されません。監査情報のクエリーはサブクエリーを使用して、監査テーブルの適用可能な行を選択します。これはスピードが遅く、インデックス作成が困難です。
有効性監査ストラテジー
  • このストラテジーは、監査上の開始リビジョンと最後のリビジョンを保存します。監査されたテーブルで挿入、更新、削除される行ごとに、有効性の開始リビジョンとともに、監査テーブルに 1 つ以上の行を挿入します。
  • 同時に、以前の監査行 (利用可能な場合) の終了リビジョンフィールドは、このリビジョンに設定されます。監査情報のクエリーは、サブクエリーの代わりに、between start and end revision の間で使用できます。つまり、追加の更新により、監査情報の永続化は多少遅くなりますが、監査情報の取得はかなり速くなります。
  • これは、インデックスを追加して改善することもできます。

監査の詳細は、永続クラスの監査についてを参照してください。アプリケーションの監査ストラテジーを設定するには、Set the Auditing Strategy を参照してください。

6.3.2. 監査ストラテジーの設定

JBoss EAP では、以下の 2 つの監査ストラテジーがサポートされています。

  • デフォルトの監査ストラテジー
  • 有効性監査ストラテジー
監査ストラテジーの定義

アプリケーションの persistence.xml ファイルで org.hibernate.envers.audit_strategy プロパティーを設定します。プロパティーが persistence.xml ファイルで設定されていない場合は、デフォルトの監査ストラテジーが使用されます。

デフォルトの監査ストラテジーの設定

<property name="org.hibernate.envers.audit_strategy" value="org.hibernate.envers.strategy.DefaultAuditStrategy"/>

有効性監査ストラテジーの設定

<property name="org.hibernate.envers.audit_strategy" value="org.hibernate.envers.strategy.ValidityAuditStrategy"/>

6.3.3. Jakarta Persistence エンティティーへの監査サポートの追加

手順

JBoss EAP は Hibernate Envers を介してエンティティー監査を使用して、永続クラスのこれまでの変更を追跡します。ここでは、Jakarta Persistence エンティティーの監査サポートの追加について説明します。

Jakarta Persistence エンティティーへの監査サポートの追加

  1. デプロイメントに適した利用可能な監査パラメーターを設定します。詳細は Configure Envers Parameters を参照してください。
  2. 監査する Jakarta Persistence エンティティーを開きます。
  3. org.hibernate.envers.Audited インターフェースをインポートします。
  4. 監査する各フィールドまたはプロパティーに @Audited アノテーションを適用するか、クラス全体に対して 1 度適用します。

    例: 2 つのフィールドの監査

    import org.hibernate.envers.Audited;
    
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Column;
    
    @Entity
    public class Person {
        @Id
        @GeneratedValue
        private int id;
    
        @Audited
        private String name;
    
        private String surname;
    
        @ManyToOne
        @Audited
        private Address address;
    
        // add getters, setters, constructors, equals and hashCode here
    }

    例: クラス全体の監査

    import org.hibernate.envers.Audited;
    
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Column;
    
    @Entity
    @Audited
    public class Person {
        @Id
        @GeneratedValue
        private int id;
    
        private String name;
    
        private String surname;
    
        @ManyToOne
        private Address address;
    
        // add getters, setters, constructors, equals and hashCode here
    }

Jakarta Persistence エンティティーが監査用に設定されている場合は、履歴の変更を保存するために _AUD というテーブルが作成されます。

6.4. Configuration (設定)

6.4.1. Envers パラメーターの設定

JBoss EAP は About Hibernate Envers を介してエンティティー監査を使用して、永続クラスのこれまでの変更を追跡します。

利用可能な Envers パラメーターの設定

  1. アプリケーションの persistence.xml ファイルを開きます。
  2. 必要に応じて Envers プロパティーを追加、削除、または設定します。利用可能なプロパティーの一覧は、Envers Configuration Properties を参照してください。

    例: Envers パラメーター

    <persistence-unit name="mypc">
      <description>Persistence Unit.</description>
      <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
      <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
      <properties>
        <property name="hibernate.hbm2ddl.auto" value="create-drop" />
        <property name="hibernate.show_sql" value="true" />
        <property name="hibernate.cache.use_second_level_cache" value="true" />
        <property name="hibernate.cache.use_query_cache" value="true" />
        <property name="hibernate.generate_statistics" value="true" />
        <property name="org.hibernate.envers.versionsTableSuffix" value="_V" />
        <property name="org.hibernate.envers.revisionFieldName" value="ver_rev" />
      </properties>
    </persistence-unit>

6.4.2. ランタイム時の監査の有効化または無効化

ランタイム時のエンティティーバージョンの監査の有効化または無効化

  1. AuditEventListener クラスをサブクラス化します。
  2. Hibernate イベントで呼び出される以下のメソッドを上書きします。

    • onPostInsert
    • onPostUpdate
    • onPostDelete
    • onPreUpdateCollection
    • onPreRemoveCollection
    • onPostRecreateCollection
  3. イベントのリスナーとしてサブクラスを指定します。
  4. 変更を監査する必要があるかどうかを判断します。
  5. 変更を監査する必要がある場合には、スーパークラスに呼び出しを渡します。

6.4.3. 条件監査の設定

Hibernate Envers は、一連のイベントリスナーを使用して、さまざまな Hibernate イベントに対する応答で監査データを永続化します。Envers JAR がクラスパスにある場合、これらのリスナーは自動的に登録されます。

条件監査の実装

  1. persistence.xml ファイルで hibernate.listeners.envers.autoRegister を false に設定します。
  2. 上書きされる各イベントリスナーをサブクラス化します。条件付き監査ロジックをサブクラスに配置し、監査を実行する必要がある場合は super メソッドを呼び出します。
  3. org.hibernate.envers.event.EnversIntegrator に類似した、org.hibernate.integrator.spi.Integrator のカスタム実装を作成します。デフォルトのクラスではなく、ステップ 2 で作成したイベントリスナーサブクラスを使用します。
  4. META-INF/services/org.hibernate.integrator.spi.Integrator ファイルを JAR に追加します。このファイルには、インターフェースを実装するクラスの完全修飾名が含まれている必要があります。

6.4.4. Envers 設定プロパティー

表6.1 エンティティーデータのバージョン管理設定パラメーター

プロパティー名デフォルト値説明

org.hibernate.envers.audit_table_prefix

 

監査されたエンティティーの名前の前に付加される文字列。監査情報を保持するエンティティーの名前を作成します。

org.hibernate.envers.audit_table_suffix

_AUD

監査されたエンティティーの名前に付加される文字列。監査情報を保持するエンティティーの名前を作成します。たとえば、テーブル名が Person のエンティティーが監査されると、Envers は、履歴データを格納する Person_AUD と呼ばれるテーブルを生成します。

org.hibernate.envers.revision_field_name

REV

改訂番号を保持する監査エンティティーのフィールド名。

org.hibernate.envers.revision_type_field_name

REVTYPE

改訂の種類を保持する監査エンティティーのフィールド名。現在の改訂の種類には、挿入を行う add、変更を行う mod、削除を行う del があります。

org.hibernate.envers.revision_on_collection_change

true

このプロパティーは、所有の変更のない関係フィールドがある場合にリビジョンを生成するかどうかを決定します。これは、一対多数の関係のコレクションであるか、または一対一の関係で mappedBy 属性を使用するフィールドになります。

org.hibernate.envers.do_not_audit_optimistic_locking_field

true

true の場合、(@Version でアノテーション付けされた) 楽観的ロックに使用されるプロパティーは自動的に監査から除外されます。

org.hibernate.envers.store_data_at_delete

false

このプロパティーは、ID のみではなく、エンティティーデータを削除するときに、エンティティーデータをリビジョンに保存するかどうかを定義します。その他のすべてのプロパティーは null とマークされます。通常、データは最後から 2 番目のバージョンにあるため、これは必須ではありません。ただし時折、最後のリビジョンでアクセスすることが簡単で、より効率的になる場合があります。ただし、これは、削除前に含まれるエンティティーのデータが 2 回保存されることを意味します。

org.hibernate.envers.default_schema

null (通常のテーブルと同じ)

監査テーブルに使用されるデフォルトのスキーマ名。@AuditTable(schema="…​") アノテーションを使用して上書き可能。これがない場合、スキーマは通常のテーブルのスキーマと同じになります。

org.hibernate.envers.default_catalog

null (通常のテーブルと同じ)

監査テーブルに使用するデフォルトのカタログ名。@AuditTable(catalog="…​") アノテーションを使用して上書き可能。存在しない場合、カタログは通常のテーブルのカタログと同じになります。

org.hibernate.envers.audit_strategy

org.hibernate.envers.strategy.DefaultAuditStrategy

このプロパティーは、監査データの永続化時に使用する必要のある監査ストラテジーを定義します。デフォルトでは、エンティティーが変更されたリビジョンのみが保存されます。または、org.hibernate.envers.strategy.ValidityAuditStrategyでは、開始リビジョンと終了リビジョンの両方を保存します。これらを組み合わせて、監査行が有効であったタイミングを定義します。

org.hibernate.envers.audit_strategy_validity_end_rev_field_name

REVEND

監査エンティティーで終了リビジョン番号を保持するコラムの名前。このプロパティーは、妥当な監査ストラテジーが使用される場合にのみ有効です。

org.hibernate.envers.audit_strategy_validity_store_revend_timestamp

false

このプロパティーは、終了リビジョン自体に加えて、データが最後に有効であった終了リビジョンのタイムスタンプも保存すべきかどうかを定義します。これは、テーブルパーティションを使用して、リレーショナルデータベースから古い監査レコードをパージする場合に便利です。パーティショニングには、テーブルに存在するコラムが必要です。このプロパティーは ValidityAuditStrategy が使用される場合にのみ評価されます。

org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name

REVEND_TSTMP

データがまだ有効であった時点での終了リビジョンのタイムスタンプのコラム名。ValidityAuditStrategy が使用され org.hibernate.envers.audit_strategy_validity_store_revend_timestamp が true に評価します。

6.5. 監査情報のクエリー

6.5.1. クエリーを介した監査情報の取得

Hibernate Enver は、クエリーを介して監査情報を取得する機能を提供します。

注記

監査されたデータでのクエリーは、関連する subselect を伴うため、多くの場合、live データに対するクエリーよりもはるかに遅くなります。

所定リビジョンでのクラスのエンティティーのクエリー

このタイプのクエリーのエントリーポイントは以下の通りです。

AuditQuery query = getAuditReader()
    .createQuery()
    .forEntitiesAtRevision(MyEntity.class, revisionNumber);

制約は AuditEntity ファクトリークラスを使用して指定できます。以下のクエリーは、name プロパティーが John と同等のエンティティーのみを選択します。

query.add(AuditEntity.property("name").eq("John"));

以下のクエリーは、特定のエンティティーに関連するエンティティーのみを選択します。

query.add(AuditEntity.property("address").eq(relatedEntityInstance));
// or
query.add(AuditEntity.relatedId("address").eq(relatedEntityId));

その結果は、順序付け、制限でき、集計と予測 (グループ化を除く) セットを設定することができます。以下の例は、フルクエリーです。

List personsAtAddress = getAuditReader().createQuery()
    .forEntitiesAtRevision(Person.class, 12)
    .addOrder(AuditEntity.property("surname").desc())
    .add(AuditEntity.relatedId("address").eq(addressId))
    .setFirstResult(4)
    .setMaxResults(2)
    .getResultList();

所定クラスエンティティーが変更されるクエリーリビジョン

このタイプのクエリーのエントリーポイントは以下の通りです。

AuditQuery query = getAuditReader().createQuery()
    .forRevisionsOfEntity(MyEntity.class, false, true);

このクエリーには、前述の例と同じように制約を追加できます。このクエリーには、追加の方法が考えられます。

AuditEntity.revisionNumber()
監査済みエンティティーが変更されたリビジョン番号の制約、展開、および順序を指定します。
AuditEntity.revisionProperty(propertyName)
監査済みエンティティーが変更されたリビジョンに対応する、リビジョンエンティティーのプロパティーに対する制約、調整および順序付けを指定します。
AuditEntity.revisionType()
リビジョンのタイプ (ADD、MOD、DEL) へのアクセスを提供します。

クエリー結果は必要に応じて調整できます。以下のクエリーは、リビジョン番号 42 の後にentityId が変更された MyEntity クラスのエンティティーが変更する最小リビジョン番号を選択します。

Number revision = (Number) getAuditReader().createQuery()
    .forRevisionsOfEntity(MyEntity.class, false, true)
    .setProjection(AuditEntity.revisionNumber().min())
    .add(AuditEntity.id().eq(entityId))
    .add(AuditEntity.revisionNumber().gt(42))
    .getSingleResult();

リビジョンのクエリーは、プロパティーを最小限に抑えたり、最大値にしたりすることもできます。以下のクエリーは、特定のエンティティーの actualDate の値が指定の値よりも大きくなるリビジョンを選択しますが、可能な限り小さくなります。

Number revision = (Number) getAuditReader().createQuery()
    .forRevisionsOfEntity(MyEntity.class, false, true)
    // We are only interested in the first revision
    .setProjection(AuditEntity.revisionNumber().min())
    .add(AuditEntity.property("actualDate").minimize()
        .add(AuditEntity.property("actualDate").ge(givenDate))
        .add(AuditEntity.id().eq(givenEntityId)))
    .getSingleResult();

minimize() および maximize() のメソッドは基準を返します。これは、制約を追加でき、 maximized/minimized プロパティーを持つエンティティーによって満たされる必要があります。

クエリーの作成時に、2 つのブール値パラメーターが渡されます。

selectEntitiesOnly

このパラメーターは、明示的な子が設定されていない場合のみ有効です。
true の場合、クエリーの結果は、指定された制約を満たすリビジョンで変更されたエンティティーのリストになります。
falseの場合、結果は 3 つの要素の配列のリストになります。最初の要素は変更されたエンティティーインスタンスになります。次は、リビジョンデータを含むエンティティーです。カスタムエンティティーが使用されていない場合、DefaultRevisionEntity のインスタンスになります。3 番目の要素アレイはリビジョンのタイプ (ADD、MOD、DEL) になります。
selectDeletedEntities
このパラメーターは、エンティティーが削除されたリビジョンを結果に含める必要があるかどうかを指定します。true の場合、エンティティーにはリビジョンタイプ DEL が指定され、id を除くすべてのフィールドの値は null になります。

所定プロパティーを変更するエンティティーのクエリーの修正

以下のクエリーは、指定の id を持つ MyEntity のすべてのリビジョンを返します。ここでは、realDate プロパティーが変更になりました。

AuditQuery query = getAuditReader().createQuery()
  .forRevisionsOfEntity(MyEntity.class, false, true)
  .add(AuditEntity.id().eq(id));
  .add(AuditEntity.property("actualDate").hasChanged())

hasChanged 条件は、追加の基準と組み合わせることができます。以下のクエリーは、revisionNumber の生成時に MyEntity の水平スライスを返します。これは prop1 が変更されたリビジョンに限定されますが、prop2 には適用されません。

AuditQuery query = getAuditReader().createQuery()
  .forEntitiesAtRevision(MyEntity.class, revisionNumber)
  .add(AuditEntity.property("prop1").hasChanged())
  .add(AuditEntity.property("prop2").hasNotChanged());

作成されたセットには、revisionNumber よりも少ない数字のリビジョンも含まれます。これは、このクエリーを「Return all MyEntities changed in revisionNumber with prop1 modified and prop2 untouched」として読み取ることができないことを意味します。

以下のクエリーは、forEntitiesModifiedAtRevision クエリーを使用して、この結果が返される方法を示しています。

AuditQuery query = getAuditReader().createQuery()
  .forEntitiesModifiedAtRevision(MyEntity.class, revisionNumber)
  .add(AuditEntity.property("prop1").hasChanged())
  .add(AuditEntity.property("prop2").hasNotChanged());

指定リビジョンでのクエリーエンティティーの変更

以下の例は、特定のリビジョンで変更されたエンティティーの基本クエリーを示しています。指定されたリビジョンで変更されたエンティティー名と対応するクラスを取得することができます。

Set<Pair<String, Class>> modifiedEntityTypes = getAuditReader()
    .getCrossTypeRevisionChangesReader().findEntityTypes(revisionNumber);

org.hibernate.envers.CrossTypeRevisionChangesReader からもアクセス可能なクエリーは多数あります。

List<Object> findEntities(Number)
指定のリビジョンで変更された (追加、更新、削除された) すべての監査済みエンティティーのスナップショットを返します。n+1 SQL クエリーを実行します。n は、指定されたリビジョン内で変更された複数の異なるエンティティークラスです。
List<Object> findEntities(Number, RevisionType)
変更タイプでフィルターされた特定のリビジョンで変更 (追加、更新、または削除) されたすべての監査済みエンティティーのスナップショットを返します。n+1 SQL クエリーを実行します。n は、指定されたリビジョン内で変更された複数の異なるエンティティークラスです。Map<RevisionType, List<Object>>
findEntitiesGroupByRevisionType(Number)
変更操作 (追加、更新、または削除など) でグループ化されたエンティティースナップショットの一覧が含まれるマップを返します。3n+1 SQL クエリーを実行します。n は、指定されたリビジョン内で変更された複数の異なるエンティティークラスです。

6.5.2. 参照されるエンティティーのプロパティーを使用したエンティティーの関連付けのトラバース

参照されるエンティティーのプロパティーを使用して、クエリー内のエンティティーをトラバースできます。これにより、1 対 1 および多対 1 の関連付けをクエリーできます。

以下の例は、クエリーでエンティティーをトラバースする方法の一部を示しています。

  • リビジョン番号 1 では、所有者が 20 歳であるか、住所番号 30 に居住している車を見つけます。そして、車のメーカーで設定した結果の順序づけを行います。

    List<Car> resultList = auditReader.createQuery()
                    .forEntitiesAtRevision( Car.class, 1 )
                    .traverseRelation( "owner", JoinType.INNER, "p" )
                    .traverseRelation( "address", JoinType.INNER, "a" )
                    .up().up().add( AuditEntity.disjunction().add(AuditEntity.property( "p", "age" )
                           .eq( 20 ) ).add( AuditEntity.property( "a", "number" ).eq( 30 ) ) )
                    .addOrder( AuditEntity.property( "make" ).asc() ).getResultList();
  • リビジョン番号 1 では、所有者の年齢と住所番号が同じ車を見つけます。

    Car result = (Car) auditReader.createQuery()
                    .forEntitiesAtRevision( Car.class, 1 )
                    .traverseRelation( "owner", JoinType.INNER, "p" )
                    .traverseRelation( "address", JoinType.INNER, "a" )
                    .up().up().add(AuditEntity.property( "p", "age" )
                            .eqProperty( "a", "number" ) ).getSingleResult();
  • リビジョン番号 1 では、所有者の年齢が 20 歳であるか、所有者がない車すべてを見つけます。

    List<Car> resultList = auditReader.createQuery()
                    .forEntitiesAtRevision( Car.class, 1 )
                    .traverseRelation( "owner", JoinType.LEFT, "p" )
                    .up().add( AuditEntity.or( AuditEntity.property( "p", "age").eq( 20 ),
                            AuditEntity.relatedId( "owner" ).eq( null ) ) )
                    .addOrder( AuditEntity.property( "make" ).asc() ).getResultList();
  • リビジョン番号 1 では、メーカーが「car3」であり、所有者の年齢が 30 歳であるか、所有者のいない車すべてを見つけます。

    List<Car> resultList = auditReader.createQuery()
                    .forEntitiesAtRevision( Car.class, 1 )
                    .traverseRelation( "owner", JoinType.LEFT, "p" )
                    .up().add( AuditEntity.and( AuditEntity.property( "make" ).eq( "car3" ), AuditEntity.property( "p", "age" ).eq( 30 ) ) )
                    .getResultList();
  • リビジョン番号 1 では、メーカーが「car3」であるか、所有者の年齢が 10 歳であるか、あるいは所有者がいない車すべてを見つけます。

    List<Car> resultList = auditReader.createQuery()
                    .forEntitiesAtRevision( Car.class, 1 )
                    .traverseRelation( "owner", JoinType.LEFT, "p" )
                    .up().add( AuditEntity.or( AuditEntity.property( "make" ).eq( "car3" ), AuditEntity.property( "p", "age" ).eq( 10 ) ) )
                    .getResultList();

6.6. パフォーマンスチューニング

6.6.1. 他のバッチロードアルゴリズム

Hibernate では、join、select、subselect、および batch の 4 つののフェッチストラテジーのいずれかを使用して関連付けのデータを読み込むことができます。これら 4 つのストラテジーにおいて、バッチローディングでは、select フェッチの最適化ストラテジーであるため、これらのストラテジーの外で、パフォーマンスを大幅に向上させることができます。このストラテジーでは、Hibernate はプライマリーキーまたは外部キーのリストを指定して、単一の SELECT ステートメントでエンティティーインスタンスまたはコレクションのバッチを取得します。batch フェッチは、レイジー select フェッチストラテジーの最適化です。

batch フェッチの設定方法は、クラス当たりのレベルまたはコレクション当たりのレベルです。

  • クラス当たりのレベル

    Hibernate がクラス当たりのレベルでデータを読み込む場合は、クエリーの実行時にロードする関連付けのバッチサイズが必要になります。たとえば、ランタイム時に、セッションに 30 個のインスタンスの car オブジェクトがロードされているとします。各 car オブジェクトは owner オブジェクトに属します。すべての car オブジェクトを繰り返し処理し、所有者を要求する場合、lazy 読み込みでは、Hibernate は所有者ごとに 30 個の select ステートメントを発行します。これはパフォーマンスのボトルネックです。

    代わりに、Hibernate に対して、クエリーを経由する前に所有者の次のバッチのデータを事前に読み込むように指示することもできます。owner オブジェクトがクエリーされると、Hibernate は同じ SELECT ステートメントで多くのこれらのオブジェクトをクエリーします。

    事前にクエリーする owner オブジェクトの数は、設定時に指定された batch-size パラメーターによって異なります。

    <class name="owner" batch-size="10"></class>

    これにより、Hibernate は、後で必要と予想される 10 個以上の owner オブジェクトをクエリーするようになります。ユーザーが car Aowner にクエリーすると、car Bowner はすでにバッチロードの一部として読み込まれている可能性があります。ユーザーがデータベースに移動 (および SELECT ステートメントを実行) する代わりに、実際に car Bowner が必要な場合は、現在のセッションから値を取得できます。

    batch-size パラメーターに加えて、Hibernate 4.2.0 ではバッチロードのパフォーマンスを強化する新しい設定項目が導入されました。設定項目は Batch Fetchstyle 設定と呼ばれ、hibernate.batch_fetch_style パラメーターによって指定されます。

    LEGACY、PADDED、DYNAMIC といった異なるバッチフェッチスタイルがサポートされています。使用するスタイルを指定するには、org.hibernate.cfg.AvailableSettings#BATCH_FETCH_STYLE を使用します。

    • LEGACY: 読み込みのレガシースタイルでは、ArrayHelper.getBatchSizes(int) に基づく事前ビルドされたバッチサイズセットが使用されます。バッチは、既存のバッチ可能な識別子の数からの次に小さな事前ビルドされたバッチサイズを使用してロードされます。

      上記の例で、batch-size が 30 の場合、事前ビルドされたバッチサイズは [30, 15, 10, 9, 8, 7,..., 1] になります。ロード 29 識別子のバッチ処理を試みると、15、10、および 4 のバッチが発生します。対応する SQL クエリーは 3 つあり、各クエリーはデータベースから 15、10、および 4 の所有者 (owner) を読み込みます。

    • PADDED - PADDED は、バッチローディングの LEGACY スタイルに似ています。依然として事前ビルドされたバッチサイズを使用していますが、次に大きなバッチサイズを使用し、追加の識別子プレースホルダーをパディングします。

      上記の例と同様に、30 個の owner オブジェクトを初期化する場合、データベースに対してクエリーが実行されるのは 1 つのみとなります。

      ただし、29 個の owner オブジェクトが初期化される場合でも、Hibernate は依然としてバッチサイズ 30 の SQL select ステートメントのみを実行し、識別子が連続する追加スペースがパディングされます。

    • Dynamic - バッチサイズの制限に準拠していますが、このスタイルのバッチロードは、実際に読み込まれるオブジェクト数を使用して SQL SELECT ステートメントを動的に構築します。

      たとえば、owner オブジェクトが 30 個で、最大バッチサイズが 30 の場合、30 個の owner オブジェクトを取得する呼び出しは、1 つの SQL SELECT ステートメントになります。35 個を取得する呼び出しは、バッチサイズ 30 と 5 の 2 つの SQL ステートメントになります。Hibernate は、必要な数である 5 を維持するために 第 2 の SQL ステートメントを動的に変更します。また、バッチサイズは制限の 30 のままに保持します。これは、PADDED バージョンとは異なります。第 2 の SQL は PADDED されません。LEGACY スタイルとは異なり、第 2 の SQL ステートメントには固定サイズがなく、次の SQL は動的に作成されます。

      クエリーが 30 個の識別子を下回る場合、このスタイルは要求された識別子の数のみを動的に読み込みます。

  • コレクション当たりのレベル

    Hibernate では、上記の各クラス当たりのセクションにリストされているバッチフェッチサイズとスタイルを採用するロードコレクションのバッチ処理も可能です。

    前のセクションで使用した例を戻すには、各 owner オブジェクトが所有するすべての car オブジェクトをロードする必要があることを考慮してください。10 個の owner オブジェクトが現行セッションでロードされ、すべての owner で 反復すると、10 個の SELECT ステートメントが生成されます (getCars() メソッドへの呼び出しごと)。Owner のマッピングで cars コレクションのバッチフェッチを有効にすると、Hibernate は以下のようにこれらのコレクションの事前フェッチを実行できます。

    <class name="Owner"><set name="cars" batch-size="5"></set></class>

    そのため、バッチサイズが 10 個で、レガシーバッチスタイルを使用して つのコレクションをロードすると、Hibernate は つの SELECT ステートメントを実行し、各コレクションを取得します。

6.6.2. 変更不可のデータのオブジェクト参照の 2 次レベルのキャッシング

Hibernate は、パフォーマンスを改善するために自動的にデータをメモリーにキャッシュします。これは、特にほとんど変更されないデータに対して、必要なデータベースルックアップ回数を減らすインメモリーキャッシュによって実現されます。

Hibernate は以下の種類のキャッシュを維持します。1 次キャッシュとも呼ばれるプライマリーキャッシュは必須です。このキャッシュは現行セッションと関連付けられ、すべてのリクエストがそのセッションを通過する必要があります。セカンダリーキャッシュとも呼ばれる 2 次キャッシュは任意で、プライマリーキャッシュが参照された後にのみ参照されます。

データは、最初にデータを状態アレイにアセンブルすることで 2 次キャッシュに保存されます。このアレイはディープコピーされ、そのディープコピーがキャッシュに配置されます。その逆は、キャッシュからの読み取りに対して行われます。これは、変更 (変更不能データ) が変更できないデータには適切に機能しますが、変更できないデータには効率的ではありません。

データのディープコピーは、メモリー使用量と処理速度に関する負荷のかかる操作です。大きなデータセットでは、メモリーと処理速度がパフォーマンス制限の要因となります。Hibernate では、変更不能なデータがコピーされるのではなく、参照されるように指定できます。Hibernate は、データセット全体をコピーする代わりに、キャッシュのデータへの参照を保管できるようになりました。

これには、設定 hibernate.cache.use_reference_entries の値を true に変更します。デフォルトでは、hibernate.cache.use_reference_entriesfalse に設定されています。

hibernate.cache.use_reference_entriestrue に設定されている場合は、関連付けのない変更不能なデータオブジェクトは 2次キャッシュにコピーされず、その参照のみが保存されます。

警告

hibernate.cache.use_reference_entriestrue に設定されると、関連付けのある変更不能なデータオブジェクトが 2 次キャッシュにディープコピーされます。

付録A リファレンス資料

A.1. Hibernate プロパティー

表A.1 persistence.xml ファイルで設定できる接続プロパティー

プロパティー名説明

javax.persistence.jdbc.driver

org.hsqldb.jdbcDriver

使用する JDBC ドライバーのクラス名。

javax.persistence.jdbc.user

sa

ユーザー名

javax.persistence.jdbc.password

 

パスワード。

javax.persistence.jdbc.url

jdbc:hsqldb:.

JDBC 接続 URL。

表A.2 Hibernate 設定プロパティー

プロパティー名説明

hibernate.dialect

Hibernate org.hibernate. metaect.Dialect のクラス名。Hibernate が特定の関係データベース向けに最適化された SQL を生成できるようにします。

ほとんどの場合、Hibernate は JDBC ドライバーによって返される JDBC メタデータに基づいて適切な org.hibernate. metaect.Dialect 実装を選択できます。

hibernate.show_sql

ブール値。すべての SQL ステートメントをコンソールに書き込みます。これは、ログカテゴリー org.hibernate.SQLdebug に設定する代わりになります。

hibernate.format_sql

ブール値。pretty print で、ログとコンソールに SQL を出力します。

hibernate.default_schema

生成された SQL で指定のスキーマ/テーブルスペースを持つ修飾されていないテーブル名。

hibernate.default_catalog

生成された SQL で指定のカタログと修飾されていないテーブル名を修飾します。

hibernate.session_factory_name

org.hibernate.SessionFactory は、作成後に Java Naming および Directory Interface でこの名前に自動的にバインドされます。たとえば、jndi/composite/name.Jpa です。

hibernate.max_fetch_depth

単独の関連 (one-to-one、many-to-one) の外部結合フェッチツリーの最大深さを設定します。0 は、デフォルトの外部ジョインフェッチを無効にします。推奨の値は 0 から 3 の間です。

hibernate.default_batch_fetch_size

関連付けの Hibernate バッチフェッチのデフォルトサイズを設定します。推奨される値は 4816です。

hibernate.default_entity_mode

この SessionFactoryか ら開かれたすべてのセッションに対するエンティティー表現のデフォルトモードを設定します。値には dynamic-mapdom4jpojo が含まれます。

hibernate.order_updates

ブール値。Hibernate は、更新する製品のプライマリーキーの値で SQL 更新の順序を強制します。これにより、非常に同時になるシステムでは、トランザクションのデッドロックが少なくなります。

hibernate.generate_statistics

ブール値。有効にすると、Hibernate はパフォーマンスチューニングに役立つ統計を収集します。

hibernate.use_identifier_rollback

ブール値。有効な場合、オブジェクトが削除されると、生成された識別子プロパティーがデフォルト値にリセットされます。

hibernate.use_sql_comments

ブール値。有効にすると、Hibernate はデバッグを容易にするため、SQL 内でコメントを生成します。デフォルト値は false です。

hibernate.id.new_generator_mappings

ブール値。@GeneratedValue を使用する場合、このプロパティーには関係があります。これは、新しい IdentifierGenerator 実装が javax.persistence.GenerationType.AUTO、javax.persistence.GenerationType.TABLE および javax.persistence.GenerationType.SEQUENCE に使用されるかどうかを示します。デフォルト値は true です。

hibernate.ejb.naming_strategy

Hibernate EntityManager を使用する際に org.hibernate.cfg.NamingStrategy 実装を選択します。Hibernate.ejb.naming_strategy は Hibernate 5.0 でサポートされなくなりました。これを使用すると、非推奨のメッセージがログに記録され、split ImplicitNamingStrategy および PhysicalNamingStrategy が優先され、サポートされなくなったことを示すメッセージが削除されます。

アプリケーションが EntityManager を使用しない場合は、以下の手順に従って NamingStrategy: Hibernate Reference Documentation - Naming Strategies を設定します。

MetadataBuilder を使用したネイティブブートストラップおよび暗黙的な命名ストラテジーの適用例は、Hibernate 5.0 ドキュメントの http://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#bootstrap-native-metadata を参照してください。物理的な命名ストラテジーは、MetadataBuilder.applyPhysicalNamingStrategy() を使用して適用できます。org.hibernate.boot.MetadataBuilder, see https://docs.jboss.org/hibernate/orm/5.0/javadocs/ を参照してください。

hibernate.implicit_naming_strategy

使用する org.hibernate.boot.model.naming.ImplicitNamingStrategy クラスを指定します。hibernate.implicit_naming_strategy は、ImplicitNamingStrategy を実装するカスタムクラスの設定にも使用できます。この設定には、以下の短縮名が定義されます。

  • default - ImplicitNamingStrategyJpaCompliantImpl
  • jpa - ImplicitNamingStrategyJpaCompliantImpl
  • legacy-jpa - ImplicitNamingStrategyLegacyJpaImpl
  • legacy-hbm - ImplicitNamingStrategyLegacyHbmImpl
  • component-path - ImplicitNamingStrategyComponentPathImpl

デフォルト設定は、default の省略名の ImplicitNamingStrategy によって定義されます。デフォルト設定が空の場合、フォールバックは ImplicitNamingStrategyJpaCompliantImpl を使用します。

hibernate.physical_naming_strategy

データベースオブジェクト名に物理的な命名ルールを適用するためのプラグ可能なストラテジーコントラクト。使用する PhysicalNamingStrategy クラスを指定します。PhysicalNamingStrategyStandardImpl はデフォルトで使用されます。hibernate.physical_naming_strategy を使用して、PhysicalNamingStrategy を実装するカスタムクラスを設定することもできます。

重要

hibernate.id.new_generator_mappings の場合、新規アプリケーションはデフォルト値の true のままにする必要があります。Hibernate 3.3.x を使用した既存のアプリケーションは、シーケンスオブジェクトまたはテーブルベースのジェネレーターを使用し、後方互換性を維持するために false に変更する必要がある場合があります。

表A.3 Hibernate JDBC および接続プロパティー

プロパティー名説明

hibernate.jdbc.fetch_size

JDBC フェッチサイズを決定するゼロ以外の値 ( Statement.setFetchSize()を呼び出します)。

hibernate.jdbc.batch_size

ゼロ以外の値は、Hibernate による JDBC2 バッチ更新の使用を有効にします。推奨される値は 5 から 30 の間です。

hibernate.jdbc.batch_versioned_data

ブール値。JDBC ドライバーが executeBatch() から正しい行数を返す場合は、このプロパティーを true に設定します。その後、Hibernate は、自動的にバージョン付けされたデータにバッチ処理を使用します。デフォルト値は false です。

hibernate.jdbc.factory_class

カスタムの org.hibernate.jdbc.Batcher を選択します。ほとんどのアプリケーションでは、この設定プロパティーは必要ありません。

hibernate.jdbc.use_scrollable_resultset

ブール値。Hibernate による JDBC2 のスクロール可能な結果セットの使用を有効にします。このプロパティーは、ユーザー指定の JDBC 接続を使用する場合にのみ必要です。Hibernate は接続メタデータを使用します。

hibernate.jdbc.use_streams_for_binary

ブール値。これはシステムレベルのプロパティーです。binary または serializable を JDBC に書き込む際や、JDBC から読み込む際には、ストリームを使用します。

hibernate.jdbc.use_get_generated_keys

ブール値。PreparedStatement.getGeneratedKeys() を使用して、挿入後にネイティブに生成されたキーを取得できます。JDBC3+ ドライバーおよび JRE1.4+ が必要です。JDBC ドライバーに、Hibernate 識別子ジェネレーターの問題がある場合は false に設定します。デフォルトでは、接続メタデータを使用してドライバー機能を判断しようとします。

hibernate.connection.provider_class

Hibernate への JDBC 接続を提供するカスタム org.hibernate.connection.ConnectionProvider のクラス名。

hibernate.connection.isolation

JDBC トランザクション分離レベルを設定します。java.sql.Connection で有意な値を確認しますが、ほとんどのデータベースはすべての分離レベルをサポートしておらず、追加の非標準分離を定義することに注意してください。標準値は 1、2、4、8 です。

hibernate.connection.autocommit

ブール値。このプロパティーの使用は推奨されません。JDBC プールされた接続の自動コミットを有効にします。

hibernate.connection.release_mode

Hibernate が JDBC 接続を解放するタイミングを指定します。デフォルトでは、明示的にセッションが閉じられるか、または切断されるまで JDBC 接続が保持されます。デフォルト値 auto は Jakarta Transactions および CMT トランザクションストラテジーに after_statement を選択し、JDBC トランザクションストラテジーに after_transaction を選択します。

使用可能な値は auto (デフォルト)、on_close、after_transactionafter_statement です。

この設定は、SessionFactory.openSession によって返されるセッションにのみ影響します。SessionFactory.getCurrentSession から取得したセッションの場合、使用するために設定された CurrentSessionContext 実装はそのセッションの接続リリースモードを制御します。

hibernate.connection.<propertyName>

JDBC プロパティーを <propertyName> から DriverManager.getConnection() に渡します。

hibernate.jndi.<propertyName>

<propertyName> プロパティーを Java Naming and Directory Interface InitialContextFactory に渡します。

表A.4 Hibernate キャッシュプロパティー

プロパティー名説明

hibernate.cache.region.factory_class

カスタム CacheProvider のクラス名。

hibernate.cache.use_minimal_puts

ブール値。書き込みを最小限に抑えるために 2 次レベルのキャッシュ操作を最適化し、読み取りの頻度を上げます。この設定はクラスター化されたキャッシュで最も便利なもので、Hibernate3 ではクラスター化されたキャッシュ実装に対してデフォルトで有効になっています。

hibernate.cache.use_query_cache

ブール値。クエリーキャッシュを有効にします。個別のクエリーをキャッシュ可能に設定する必要があります。

hibernate.cache.use_second_level_cache

ブール値。<cache> マッピングを指定するクラスに対してデフォルトで有効になっている 2 次レベルのキャッシュを完全に無効にするために使用されます。

hibernate.cache.query_cache_factory

カスタム QueryCache インターフェースのクラス名。デフォルト値はビルトインの StandardQueryCache です。

hibernate.cache.region_prefix

2 次キャッシュリージョン名に使用するプレフィックス。

hibernate.cache.use_structured_entries

ブール値。Hibernate が、よりヒューマンリーダブルな形式で、2 次レベルのキャッシュにデータを格納するように強制します。

hibernate.cache.default_cache_concurrency_strategy

@Cacheable または @Cache のいずれかが使用された場合に使用するデフォルトの org.hibernate.annotations.CacheConcurrencyStrategy の名前を付与するために使用される設定。@Cache(strategy="..") は、これを上書きするのに使用されます。

表A.5 Hibernate トランザクションプロパティー

プロパティー名説明

hibernate.transaction.factory_class

Hibernate Transaction API で使用するための TransactionFactory のクラス名。デフォルトは JDBCTransactionFactory

jta.UserTransaction

アプリケーションサーバーから Jakarta Transactions UserTransaction を取得するために JTATransactionFactory によって使用される Java Naming and Directory Interface 名。

hibernate.transaction.manager_lookup_class

TransactionManagerLookup のクラス名。これは、JVM レベルキャッシングが有効な場合や、Jakarta Transactions 環境で hilo ジェネレーターを使用する場合に必要です。

hibernate.transaction.flush_before_completion

ブール値。有効にすると、トランザクションの完了前のフェーズでセッションが自動的にフラッシュされます。組み込みおよび自動セッションコンテキスト管理が推奨されます。

hibernate.transaction.auto_close_session

ブール値。有効にすると、トランザクションの完了フェーズ中にセッションが自動的に閉じられます。組み込みおよび自動セッションコンテキスト管理が推奨されます。

表A.6 その他の Hibernate プロパティー

プロパティー名説明

hibernate.current_session_context_class

「現在」の Session セッションのスコープ設定にカスタムストラテジーを指定します。値には、jtathreadmanagedcustom.Class が含まれます。

hibernate.query.factory_class

HQL パーサー実装 ( org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory または org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory) を選択します。

hibernate.query.substitutions

Hibernate クエリーのトークンから SQL トークン (トークンは関数またはリテラル名) にマップするために使用されます。たとえば、hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC

hibernate.query.conventional_java_constants

Java の定数が Java の命名規則に従うかどうかを示します。デフォルトは false です。既存のアプリケーションは、従来の Java 定数がアプリケーションで使用されている場合にのみ true に設定できます。

これを true に設定すると、エイリアスが Java 命名規則に準拠するかどうかを確認するだけで、Hibernate はエイリアスを Java の定数として処理する必要があるかどうかを判別できるため、パフォーマンスが大幅に向上します。

このプロパティーを false に設定すると、Hibernate はエイリアスをクラス (アプリケーションのオーバーヘッド) としてロードし、Java の定数として処理する必要があります。エイリアスがクラスとしてロードされない場合、Hibernate はエイリアスを Java の定数として処理します。

hibernate.hbm2ddl.auto

SessionFactory の作成時にスキーマをデータベースに自動的に検証またはエクスポートします。Create-dropSessionFactory を明示的に閉じると、データベーススキーマがドロップされます。プロパティー値のオプションはvalidateupdatecreatecreate-drop です。

hibernate.hbm2ddl.import_files

SessionFactory の作成時に実行される SQL Mission ステートメントが含まれるオプションのファイルのコンマ区切りの名前です。これは、テストまたはデモンストレーションに役立ちます。たとえば、AIA ステートメントを追加すると、デプロイ時にデータベースが最小限のデータセットでデータが投入されます。値の例は /humans.sql,/dogs.sql です。

ファイルの順序は重要です。以下のファイルのステートメントの前に特定ファイルのステートメントが実行されるためです。これらのステートメントは、たとえば hibernate.hbm2ddl.autocreate or create-drop に設定されている場合にのみ実行されます。

hibernate.hbm2ddl.import_files_sql_extractor

カスタム mportSqlCommandExtractor のクラス名デフォルトは、ビルトインの SingleLineSqlCommandExtractor です。これは、各インポートファイルから単一の SQL ステートメントを抽出する専用パーサーを実装する際に便利です。Hibernate は、複数の行 (各ステートメントの最後で必須のセミコロン) に散在する命令/コメントおよび引用符で囲まれた文字列をサポートする、複数の LinesLookupCommandLookupor も提供します。

hibernate.bytecode.use_reflection_optimizer

ブール値。これはシステムレベルのプロパティーで、hibernate.cfg.xml ファイルで設定することはできません。ランタイムの反映の代わりにバイトコード操作の使用を有効にします。リフレクションはトラブルシューティング時に役に立つことがあります。Hibernate では、最適化者が無効であっても cglib または javassist のいずれかが常に必要になります。

hibernate.bytecode.provider

javassist または cglib は、バイト操作エンジンとして使用できます。デフォルトは javassist です。値は javassist または cglibです。

表A.7 Hibernate SQL ダイアレクト (hibernate.dialect)

RDBMSダイアレクト

DB2

org.hibernate.dialect.DB2Dialect

DB2 AS/400

org.hibernate.dialect.DB2400Dialect

DB2 OS390

org.hibernate.dialect.DB2390Dialect

Adobird

org.hibernate.dialect.FirebirdDialect

FrontBase

org.hibernate.dialect.FrontbaseDialect

H2 Database

org.hibernate.dialect.H2Dialect

HypersonicSQL

org.hibernate.dialect.HSQLDialect

Informix

org.hibernate.dialect.InformixDialect

Ingres

org.hibernate.dialect.IngresDialect

Interbase

org.hibernate.dialect.InterbaseDialect

MariaDB 10

org.hibernate.dialect.MariaDB10Dialect

MariaDB Galera Cluster 10

org.hibernate.dialect.MariaDB10Dialect

Mckoi SQL

org.hibernate.dialect.MckoiDialect

Microsoft SQL Server 2000

org.hibernate.dialect.SQLServerDialect

Microsoft SQL Server 2005

org.hibernate.dialect.SQLServer2005Dialect

Microsoft SQL Server 2008

org.hibernate.dialect.SQLServer2008Dialect

Microsoft SQL Server 2012

org.hibernate.dialect.SQLServer2012Dialect

Microsoft SQL Server 2014

org.hibernate.dialect.SQLServer2012Dialect

Microsoft SQL Server 2016

org.hibernate.dialect.SQLServer2012Dialect

MySQL5

org.hibernate.dialect.MySQL5Dialect

MySQL5.5

org.hibernate.dialect.MySQL55Dialect

MySQL5.7

org.hibernate.dialect.MySQL57Dialect

Oracle (すべてのバージョン)

org.hibernate.dialect.OracleDialect

Oracle 9i

org.hibernate.dialect.Oracle9iDialect

Oracle 10g

org.hibernate.dialect.Oracle10gDialect

Oracle 11g

org.hibernate.dialect.Oracle10gDialect

Oracle 12c

org.hibernate.dialect.Oracle12cDialect

Pointbase

org.hibernate.dialect.PointbaseDialect

PostgreSQL

org.hibernate.dialect.PostgreSQLDialect

PostgreSQL 9.2

org.hibernate.dialect.PostgreSQL9Dialect

PostgreSQL 9.3

org.hibernate.dialect.PostgreSQL9Dialect

PostgreSQL 9.4

org.hibernate.dialect.PostgreSQL94Dialect

Postgres Plus Advanced Server

org.hibernate.dialect.PostgresPlusDialect

Progress

org.hibernate.dialect.ProgressDialect

SAP DB

org.hibernate.dialect.SAPDBDialect

Sybase

org.hibernate.dialect.SybaseASE15Dialect

Sybase 15.7

org.hibernate.dialect.SybaseASE157Dialect

Sybase 16

org.hibernate.dialect.SybaseASE157Dialect

Sybase Anywhere

org.hibernate.dialect.SybaseAnywhereDialect

重要

hibernate.dialect プロパティーは、アプリケーションデータベースの適切な org.hibernate. denialect.Dialect サブクラスに設定する必要があります。ダイアレクトが指定されている場合、Hibernate は他のプロパティーの一部に対して適切なデフォルトを使用します。これは、手動で指定する必要がないことを意味します。





Revised on 2021-11-28 22:08:43 +1000