The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.
このページを編集

Hibernate ORM と Jakarta Persistence の使用

Hibernate ORM は、Jakarta Persistence (旧称 JPA) のデファクトスタンダード実装であり、Object Relational Mapper の全機能を提供します。Quarkus で見事に機能します。

ソリューション

次のセクションの手順に従って、アプリケーションをステップバイステップで作成することをお勧めします。ただし、完成した例にそのまま進むこともできます。

Git リポジトリーをクローンする: git clone https://github.com/quarkusio/quarkus-quickstarts.git 、または アーカイブ をダウンロードします。

ソリューションは hibernate-orm-quickstart ディレクトリー にあります。

Hibernate ORM のセットアップと設定

Quarkus で Hibernate ORM を使用する場合、設定のために persistence.xml リソースを用意する必要はありません。

このような古典的な設定ファイルを使用することも選択肢の 1 つですが、特定の高度なニーズがない限り不要です。そのため、まずは Hibernate ORM を persistence.xml リソースなしで設定する方法を見ていきましょう。

Quarkus では、以下を行うだけです。

  • application.properties に設定を追加する

  • エンティティーに @Entity やその他のマッピングアノテーションを通常通りに付与する

その他の設定ニーズは自動化されています。Quarkus は、いくつかの定見に基づいた選択と経験に基づいた推測を行います。

以下の依存関係をプロジェクトに追加してください。

  • Hibernate ORM エクステンション: io.quarkus:quarkus-hibernate-orm

  • JDBC ドライバーエクステンション。以下のオプションを使用できます。

例えば、以下のようになります。

pom.xml
<!-- Hibernate ORM specific dependencies -->
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-hibernate-orm</artifactId>
</dependency>

<!-- JDBC driver dependencies -->
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
build.gradle
// Hibernate ORM specific dependencies
implementation("io.quarkus:quarkus-hibernate-orm")

// JDBC driver dependencies
implementation("io.quarkus:quarkus-jdbc-postgresql")

@Entity で永続オブジェクトにアノテーションを付けてから、 application.properties で関連する設定プロパティーを追加します。

application.properties
quarkus.datasource.db-kind = postgresql (1)

quarkus.hibernate-orm.schema-management.strategy=drop-and-create (2)

%prod.quarkus.datasource.username = hibernate
%prod.quarkus.datasource.password = hibernate
%prod.quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/hibernate_db
1 データソースを設定します
2 起動時にデータベースを削除して作成します (スキーマのみを更新するには update を使用します)。

これらの設定プロパティーは、通常の Hibernate ORM 設定ファイルにあるものとは異なることに注意してください。これらは多くの場合 Hibernate ORM の設定プロパティーに対応していますが、名前が異なる場合があり、必ずしも 1 対 1 で対応しているわけではありません。

また、Quarkus は多くの Hibernate ORM の設定を自動的に行い、多くの場合、より現代的なデフォルト値を使用します。

application.properties で設定可能な項目のリストについては、 Hibernate ORM の設定リファレンス を参照してください。

Hibernate ORM エクステンションがプロジェクトの依存関係に含まれていれば、Quarkus の datasource 設定に基づいて EntityManagerFactory が作成されます。

ダイアレクトはデータソースに基づいて自動的に選択および設定されます。 データベースにより正確に一致するように設定 したい場合もあるでしょう。

その後、 EntityManager をスムーズに注入できます。

Hibernate を使用したアプリケーション Bean の例
@ApplicationScoped
public class SantaClausService {
    @Inject
    EntityManager em; (1)

    @Transactional (2)
    public void createGift(String giftDescription) {
        Gift gift = new Gift();
        gift.setName(giftDescription);
        em.persist(gift);
    }
}
1 エンティティーマネージャーを注入して活用する
2 CDI Bean メソッドに @Transactional を付けると、 EntityManager がトランザクションに参加し、コミット時にフラッシュされます。
エンティティーの例
@Entity
public class Gift {
    private Long id;
    private String name;

    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

Hibernate ORM の起動時に SQL 文をロードするには、 resources ディレクトリーのルートに import.sql ファイルを追加します。このスクリプトには任意の SQL DML 文を含めることができます。各ステートメントは必ずセミコロンで終了させてください。

これは、テストやデモ用のデータセットを用意しておくのに便利です。

データベースを変更するメソッド (例: entity.persist() ) は必ずトランザクション内でラップするようにしてください。CDI Bean メソッドに @Transactional をマークすれば、そのメソッドがトランザクションの境界になります。REST エンドポイントコントローラーのようなアプリケーションのエントリーポイントの境界でこれを行うことをお勧めします。

ダイアレクト

サポートされるデータベース

サポートされているデータベース では、 Hibernate ORM ダイアレクト を明示的に設定する必要はありません。データソースに基づいて自動的に選択されます。

デフォルトでは、ダイアレクトはデータベースの最小サポートバージョンをターゲットとするように設定されています。

Hibernate ORM がより効率的な SQL を生成し、ワークアラウンドを回避して、より多くのデータベース機能を活用できるようにするために、データベースバージョンを明示的に設定できます。

明示的な db-version を持つ application.properties
quarkus.datasource.db-kind = postgresql
quarkus.datasource.db-version = 18.1 (1)

%prod.quarkus.datasource.username = hibernate
%prod.quarkus.datasource.password = hibernate
%prod.quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/hibernate_db
1 データベースのバージョンを設定します。Hibernate ORM ダイアレクトはそのバージョンをターゲットにします。

原則として、ここで設定するバージョンはできるだけ高くする必要がありますが、アプリケーションが接続する可能性のあるすべてのデータベースのバージョン以下である必要があります。

上述したように、バージョンは quarkus.datasource.db-version 設定プロパティーを介して明示的に事前設定するか、Quarkus のビルドプロセスによってデータベースの最小サポートバージョンに暗黙的に設定されます。Quarkus は起動時に、この事前設定されたバージョンと実際のデータベースバージョンを照合しようとし、実際のバージョンの方が低い場合は起動に失敗します。

これは安全策です。設定されたバージョンよりも古いデータベースを使用すると、Hibernate ORM が無効な SQL を生成し、実行時例外が発生する可能性があるためです。

データベースにアクセスできない場合は警告がログに記録されますが、起動は続行されます。起動時にデータベースにアクセスできないことがわかっている場合は、 quarkus.hibernate-orm.database.version-check.enabled=false を使用して、オプションでバージョンチェックを無効にできます。

その他のデータベース

データベースに対応する Quarkus エクステンションがない 場合、または何らかの理由でデフォルト設定がニーズに合わない場合は、 Hibernate ORM ダイアレクト を明示的に設定する必要があります。

明示的な dialect を持つ application.properties
quarkus.datasource.db-kind = postgresql

quarkus.hibernate-orm.dialect=Cockroach (1)

%prod.quarkus.datasource.username = hibernate
%prod.quarkus.datasource.password = hibernate
%prod.quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:26257/hibernate_db
1 Hibernate ORM ダイアレクトを設定します。

組み込みダイアレクトの場合、指定できる値は ダイアレクトの公式リスト にある名前のいずれかで、 Dialect の接尾辞を 除いた ものです。例えば CockroachDialect の場合は Cockroach となります。

サードパーティーのダイアレクトの場合、期待される値は完全修飾クラス名です。例えば com.acme.hibernate.AcmeDbDialect です。

その場合、JDBC ドライバーや Hibernate ORM ダイアレクトが GraalVM ネイティブ実行可能ファイルで正しく動作しない可能性があることに留意してください。

サポートされているデータベース と同様に、Hibernate ORM を最大限に活用するために、DB バージョンを明示的に設定できます。

明示的な dialectdb-version を持つ application.properties
quarkus.datasource.db-kind = postgresql
quarkus.datasource.db-version = 25.4 (1)

quarkus.hibernate-orm.dialect=Cockroach (2)

%prod.quarkus.datasource.username = hibernate
%prod.quarkus.datasource.password = hibernate
%prod.quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:26257/hibernate_db
1 データベースのバージョンを設定します。Hibernate ORM ダイアレクトはそのバージョンをターゲットにします。ここでは CockroachDB をターゲットにしているため、PostgreSQL のバージョンではなく CockroachDB のバージョンを渡しています。
2 Hibernate ORM ダイアレクトを設定します。

データベースの切り替え

データベースマルチテナンシー を有効にすると、Hibernate ORM は実行時に同じ永続化ユニットに対して複数のデータソースを使用します。デフォルトでは Quarkus はどのデータソースが使用されるかを判断できないため、Hibernate ORM で使用するダイアレクトを検出できなくなります。

そのため、 データベースマルチテナンシー を有効にする場合は、 quarkus.hibernate-orm.datasource=base ( base はデータソース名) のように、実行時に使用されるデータソースの 1 つを Hibernate ORM 設定で明示的に指定することを推奨します。

そうすることで、Quarkus はそのデータソースからデータベースのバージョンと (可能であれば) ダイアレクトを推測します。サポートされていないデータベースの場合は、 このセクション で説明したように、依然として Hibernate ORM ダイアレクトを明示的に設定する必要がある場合があります。

Hibernate ORM の設定プロパティー

EntityManagerFactory を洗練させたり、Quarkus の推測を導くのに役立つ、さまざまなオプションのプロパティーがあります。

デフォルトのデータソースが設定されている限り、必須のプロパティーはありません。

プロパティーが設定されていない場合、Quarkus は通常、Hibernate ORM のセットアップに必要なすべてを推測し、デフォルトのデータソースを使用するように構成します。

Hibernate ORM の設定リファレンス にリストされている設定プロパティーを使用すると、このようなデフォルト値を上書きしたり、さまざまな側面をカスタマイズおよび調整したりできます。

application.properties 内で persistence.xmlquarkus.hibernate-orm.* プロパティーを混在させないでください。Quarkus は例外をスローします。どちらのアプローチを使用するか決めてください。

クラスパスに無視したい persistence.xml が含まれている場合は、次の設定プロパティーを設定してください。

quarkus.hibernate-orm.persistence-xml.ignore=true

複数の永続化ユニット

複数の永続化ユニットのセットアップ

Quarkus の設定プロパティーを使用して、複数の永続化ユニットを定義することが可能です。

quarkus.hibernate-orm. 名前空間のルートにあるプロパティーは、デフォルトの永続化ユニットを定義します。例えば、以下のスニペットはデフォルトのデータソースとデフォルトの永続化ユニットを定義しています。

quarkus.datasource.db-kind=h2
quarkus.datasource.jdbc.url=jdbc:h2:mem:default;DB_CLOSE_DELAY=-1

quarkus.hibernate-orm.schema-management.strategy=drop-and-create

マップベースのアプローチを使用して、名前付きの永続化ユニットを定義することが可能です。

quarkus.datasource."users".db-kind=h2 (1)
quarkus.datasource."users".jdbc.url=jdbc:h2:mem:users;DB_CLOSE_DELAY=-1

quarkus.datasource."inventory".db-kind=h2 (2)
quarkus.datasource."inventory".jdbc.url=jdbc:h2:mem:inventory;DB_CLOSE_DELAY=-1

quarkus.hibernate-orm."users".schema-management.strategy=drop-and-create (3)
quarkus.hibernate-orm."users".datasource=users (4)
quarkus.hibernate-orm."users".packages=org.acme.model.user (5)

quarkus.hibernate-orm."inventory".schema-management.strategy=drop-and-create (6)
quarkus.hibernate-orm."inventory".datasource=inventory
quarkus.hibernate-orm."inventory".packages=org.acme.model.inventory
1 users という名前のデータソースを定義します。
2 inventory という名前のデータソースを定義します。
3 users という名前の永続化ユニットを定義します。
4 永続化ユニットが使用するデータソースを定義します。
5 この設定プロパティーは重要ですが、これについては少し後で説明します。
6 inventory データソースを指す inventory という名前の永続化ユニットを定義します。

デフォルトのデータソースと名前付きデータソースを混在させることも、どちらか一方のみにすることもできます。

デフォルトの永続化ユニットは、デフォルトでデフォルトデータソースを指します。名前付き永続化ユニットの場合、 datasource プロパティーは必須です。 datasource<default> (デフォルトデータソースの内部名) に設定することで、永続化ユニットをデフォルトデータソースに向けることができます。

複数の永続化ユニットが同じデータソースを指すようにすることは、完全に有効です。

モデルクラスの永続化ユニットへのアタッチメント

モデルクラスを永続化ユニットにアタッチする方法は 2 つあり、これらを混在させるべきではありません。

  • packages 設定プロパティー経由。

  • @io.quarkus.hibernate.orm.PersistenceUnit パッケージレベルアノテーション経由。

両方が混在している場合、アノテーションは無視され、 packages 設定プロパティーのみが考慮されます。

packages 設定プロパティーの使用は簡単です。

quarkus.hibernate-orm.schema-management.strategy=drop-and-create
quarkus.hibernate-orm.packages=org.acme.model.defaultpu

quarkus.hibernate-orm."users".schema-management.strategy=drop-and-create
quarkus.hibernate-orm."users".datasource=users
quarkus.hibernate-orm."users".packages=org.acme.model.user

この設定スニペットは 2 つの永続化ユニットを作成します。

  • デフォルトの永続化ユニット。 org.acme.model.defaultpu パッケージ (サブパッケージを含む) 下のすべてのモデルクラスを含みます。

  • users という名前の永続化ユニット。 org.acme.model.user パッケージ (サブパッケージを含む) 下のすべてのモデルクラスを含みます。

1 つの永続化ユニットに複数のパッケージをアタッチできます。

quarkus.hibernate-orm."users".packages=org.acme.model.shared,org.acme.model.user

org.acme.model.shared および org.acme.model.user パッケージ下のすべてのモデルクラスが、 users 永続化ユニットにアタッチされます。

特定のモデルクラスを複数の永続化ユニットにアタッチすることもサポートされています。

モデルクラスは、指定された永続化ユニットに一貫して追加される必要があります。これは、あるエンティティーのすべての依存モデルクラス (マッピングされたスーパークラス、埋め込み可能クラスなど) も同じ永続化ユニットにアタッチされる必要があることを意味します。パッケージレベルで永続化ユニットを扱っているため、これは十分に単純なはずです。

Panache エンティティーは、1 つの永続化ユニットにしかアタッチできません。

複数の永続化ユニットにアタッチされたエンティティーでは、Panache を使用できません。ただし、2 つのアプローチを組み合わせることは可能で、複数の永続化ユニットが必要な場合に Panache エンティティーと従来のエンティティーを混在させることができます。

これに関するユースケースがあり、簡素化された Panache のアプローチを乱さずに実装するための優れたアイデアがある場合は、 quarkus-dev メーリングリスト でご連絡ください。

モデルクラスを永続化ユニットにアタッチする 2 つ目の方法は、パッケージレベルの @io.quarkus.hibernate.orm.PersistenceUnit アノテーションを使用することです。繰り返しますが、これら 2 つのアプローチを混在させることはできません。

packages 設定プロパティーを使用した上記と同様の構成を得るには、以下の内容の package-info.java ファイルを作成します。

@PersistenceUnit("users") (1)
package org.acme.model.user;

import io.quarkus.hibernate.orm.PersistenceUnit;
1 Jakarta Persistence のアノテーションではなく、 @io.quarkus.hibernate.orm.PersistenceUnit アノテーションを使用することに注意してください。

モデルクラスに対する @PersistenceUnit の定義はパッケージレベルでのみサポートしており、このケースでクラスレベルでの @PersistenceUnit アノテーションの使用はサポートされていません。

設定プロパティーの場合と同様に、アノテーションが付与されたパッケージだけでなく、そのすべてのサブパッケージも考慮されることに注意してください。

CDI 統合

エントリーポイントの注入

Quarkus で Hibernate ORM を使用することに慣れている場合は、CDI を使用してすでに EntityManager を注入しているでしょう。

@Inject
EntityManager entityManager;

これはデフォルトの永続化ユニットの EntityManager を注入します。

名前付き永続化ユニット (この例では users) の EntityManager を注入するのは簡単です。

@Inject
@PersistenceUnit("users") (1)
EntityManager entityManager;
1 ここでも、同じ @io.quarkus.hibernate.orm.PersistenceUnit アノテーションを使用します。

注入された EntityManager または Session インスタンスはプロキシーであり、操作にはアクティブなトランザクションが必要です。

デフォルトでは、リクエストスコープ内であればトランザクションなしで読み取り専用操作に使用することも可能ですが、 quarkus.hibernate-orm.request-scoped.enabledfalse に設定することでこの機能を無効にできます。

まったく同じ仕組みで名前付き永続化ユニットの EntityManagerFactory を注入できます。

@Inject
@PersistenceUnit("users")
EntityManagerFactory entityManagerFactory;

EntityManagerEntityManagerFactory に加えて、Quarkus は以下の JPA/Hibernate コンポーネントの注入もサポートしています。

@Inject
CriteriaBuilder criteriaBuilder;

@Inject
HibernateCriteriaBuilder hibernateCriteriaBuilder;

@Inject
Metamodel metamodel;

@Inject
jakarta.persistence.Cache cache;

@Inject
org.hibernate.Cache cache;

@Inject
jakarta.persistence.PersistenceUnitUtil persistenceUnitUtil;

@Inject
jakarta.persistence.SchemaManager schemaManager;

@Inject
org.hibernate.relational.SchemaManager schemaManager;

これらのコンポーネントは、特定の永続化ユニット修飾子を使用して注入することもできます。

@Inject
@PersistenceUnit("users")
CriteriaBuilder criteriaBuilder;

コンバーターとエンティティーリスナーのプラグイン

Hibernate ORM 用の Quarkus エクステンションは、 属性コンバーターエンティティーリスナー の Hibernate ORM への注入をサポートしています。

通常の Hibernate ORM と同じように使用し (上記のリンク先ドキュメントを参照)、コンバーター/リスナーの実装内で必要に応じて CDI 機能 ( @Inject@PostConstruct@PreDestroy など) を利用してください。

CDI スコープが指定されていない場合、コンバーター/リスナーは @Dependent であるかのように振る舞い、使用される永続化ユニットごとに 1 回インスタンス化されます。

コンバーター/リスナーのクラスに @ApplicationScoped などのアノテーションを付けることで、CDI スコープを強制できます。

非常に特殊なシナリオで、CDI アノテーション ( @Inject など) を使用しているにもかかわらず、コンバーター/リスナーでの CDI の使用を抑制する必要がある場合は、 @Vetoed を付与してください。その場合、クラスは Hibernate ORM によってデフォルトコンストラクターを介してインスタンス化されます。

その他のカスタムコンポーネントのプラグイン

Hibernate ORM 用の Quarkus エクステンションは、 @PersistenceUnitExtension アノテーションが付いたコンポーネントを Hibernate Search に自動的に注入します。

このアノテーションは、オプションで @PersistenceUnitExtension(name = "nameOfYourPU") を使用して特定の永続化ユニットをターゲットにできます。

この機能は、以下のコンポーネントタイプで使用できます。

org.hibernate.Interceptor

インターセプター を参照してください。

org.hibernate.resource.jdbc.spi.StatementInspector

ステートメントインスペクター を参照してください。

org.hibernate.type.format.FormatMapper

JSON/XML のシリアル化/デシリアル化のカスタマイズ を参照してください。

io.quarkus.hibernate.orm.runtime.tenant.TenantResolver

マルチテナンシー を参照してください。

io.quarkus.hibernate.orm.runtime.tenant.TenantConnectionResolver

プログラムによるテナント接続の解決 を参照してください。

org.hibernate.boot.model.FunctionContributor

カスタム関数、型、およびマッピング を参照してください。

org.hibernate.boot.model.TypeContributor

カスタム関数、型、およびマッピング を参照してください。

永続化ユニットのアクティブ化/非アクティブ化

永続化ユニットがビルド時に設定され、エンティティータイプまたは アクティブなデータソース が割り当てられている場合、その永続化ユニットはデフォルトでアクティブになります。Quarkus は、アプリケーションの起動時に対応する Hibernate ORM SessionFactory を開始します。

実行時に永続化ユニットを非アクティブ化するには、 quarkus.hibernate-orm[.optional name].activefalse に設定します。

永続化ユニットがアクティブでない場合は、以下のようになります。

  • SessionFactory はアプリケーションの起動中に開始されません。

  • @Inject SessionFactory sf@Inject Session session など、永続化ユニットに関連する静的 CDI 注入ポイントは、アプリケーションの起動に失敗する原因となります。

  • CDI.getBeanContainer()Arc.instance() 、または注入された Instance<Session> などを通じた永続化ユニットの動的な取得は、例外がスローされる原因となります。

  • 永続化ユニットを消費する他の Quarkus エクステンションが、アプリケーションの起動を失敗させる可能性があります。

    この場合、それらの他のエクステンションも非アクティブ化する必要があります。

これは特に、アプリケーションが 実行時に事前に決められたデータソースのセットの中から 1 つを使用 できるようにしたい場合に便利です。

例えば、次のような設定の場合です。

quarkus.hibernate-orm."pg".packages=org.acme.model.shared
quarkus.hibernate-orm."pg".datasource=pg
quarkus.hibernate-orm."pg".schema-management.strategy=drop-and-create
quarkus.hibernate-orm."pg".active=false
quarkus.datasource."pg".db-kind=h2
quarkus.datasource."pg".active=false
%prod.quarkus.datasource."pg".jdbc.url=jdbc:postgresql:///your_database

quarkus.hibernate-orm."oracle".packages=org.acme.model.shared
quarkus.hibernate-orm."oracle".datasource=oracle
quarkus.hibernate-orm."oracle".schema-management.strategy=drop-and-create
quarkus.hibernate-orm."oracle".active=false
quarkus.datasource."oracle".db-kind=oracle
quarkus.datasource."oracle".active=false
%prod.quarkus.datasource."oracle".jdbc.url=jdbc:oracle:///your_database

実行時に quarkus.hibernate-orm."pg".active=true および quarkus.datasource."pg".active=true設定 すると、PostgreSQL の永続化ユニットとデータソースのみが利用可能になります。また、実行時に quarkus.hibernate-orm."oracle".active=true および quarkus.datasource."oracle".active=true を設定すると、Oracle の永続化ユニットとデータソースのみが利用可能になります。

カスタム設定プロファイル を使用すると、このようなセットアップを簡素化できます。上記の設定に以下のプロファイル固有の設定を追加することで、 quarkus.profile を設定 するだけで実行時に永続化ユニット/データソースを選択できます。例えば quarkus.profile=prod,pgquarkus.profile=prod,oracle です。

%pg.quarkus.hibernate-orm."pg".active=true
%pg.quarkus.datasource."pg".active=true
# Add any pg-related runtime configuration here, prefixed with "%pg."

%oracle.quarkus.hibernate-orm."oracle".active=true
%oracle.quarkus.datasource."oracle".active=true
# Add any oracle-related runtime configuration here, prefixed with "%oracle."

このセットアップでは、 アクティブな 永続化ユニットのみにアクセスするように注意してください。これを実現するには、 @Any 修飾子を付けた InjectableInstance<SessionFactory> または InjectableInstance<Session> を注入し、 getActive() を呼び出します。

import io.quarkus.arc.InjectableInstance;
@ApplicationScoped
public class MyConsumer {
    @Inject
    @Any
    InjectableInstance<Session> session;

    public void doSomething() {
        Session sessionForActivePersistenceUnit = session.getActive();
        // ...
    }
}

あるいは、デフォルトの永続化ユニットの Bean 用に CDI Bean プロデューサー を定義することもできます。この Bean プロデューサーは現在アクティブな名前付き永続化ユニットにリダイレクトします。これにより、以下に示すように Bean を直接注入できるようになります。

public class MyProducer {
    @Inject
    @PersistenceUnit("pg")
    InjectableInstance<Session> pgSessionBean; (1)

    @Inject
    @PersistenceUnit("oracle")
    InjectableInstance<Session> oracleSessionBean;

    @Produces (2)
    @ApplicationScoped
    public Session session() {
        if (pgSessionBean.getHandle().getBean().isActive()) { (3)
            return pgSessionBean.get();
        } else if (oracleSessionBean.getHandle().getBean().isActive()) { (3)
            return oracleSessionBean.get();
        } else {
            throw new RuntimeException("No active persistence unit!");
        }
    }
}

@ApplicationScoped
public class MyConsumer {
    @Inject
    Session session; (4)

    public void doSomething() {
        // .. just use the injected session ...
    }
}
1 Session を直接注入しないでください。非アクティブな Bean を注入すると起動に失敗します。代わりに InjectableInstance<Session> を注入してください。
2 デフォルトのセッションを定義する CDI プロデューサーメソッドを宣言します。これは、どの永続化ユニットがアクティブかに応じて、PostgreSQL または Oracle のいずれかを選択します。
3 Bean を取得する前に、その Bean がアクティブかどうかを確認します。
4 唯一のアクティブな永続化ユニットを注入します。

persistence.xml を使用した Hibernate ORM のセットアップと設定

Hibernate ORM をセットアップして設定するには、 application.properties の使用 が推奨されますが、代わりに META-INF/persistence.xml ファイルを使用することもできます。これは主に既存のコードを Quarkus に移行する際に役立ちます。

persistence.xml ファイルの使用にはいくつかの制約が伴います。

  • persistence.xml で定義された永続化ユニットは、常に デフォルトのデータソース を使用します。

  • persistence.xml で定義された永続化ユニットは明示的に設定する必要があります。Quarkus は環境関連設定の注入を最小限に抑えます。

    特に、Quarkus はデータソースに基づいたダイアレクトやデータベースバージョンの自動設定を行わないため、Hibernate ORM のデフォルト設定がニーズに合わない場合は、 persistence.xmlhibernate.dialect / jakarta.persistence.database-product-name や、場合によっては jakarta.persistence.database-product-version などの設定を含める必要があります。

  • persistence.xml の使用は、 application.properties での quarkus.hibernate-orm.* プロパティーの使用と互換性がありません。これらを混在させると、Quarkus は例外をスローします。

  • persistence.xml を使用する場合、 application.properties を使用 する場合と比較して、利用できない機能や Quarkus ドキュメントでの限られたガイダンス、適用できない解決策を提示するエラーメッセージ (例: quarkus.hibernate-orm.* プロパティーの使用) などにより、開発者エクスペリエンスが低下する可能性があります。

クラスパスに無視したい persistence.xml が含まれている場合は、次の設定プロパティーを設定してください。

quarkus.hibernate-orm.persistence-xml.ignore=true

pom.xml の依存関係と Java コードは前の例と同じになります。唯一の違いは、 META-INF/persistence.xml で Hibernate ORM 設定を指定することです。

persistence.xml リソースの例
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
             http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
             version="2.1">

    <persistence-unit name="CustomerPU" transaction-type="JTA">

        <description>My customer entities</description>

        <properties>
            <!-- Connection specific -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>

            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>

            <!--
                Optimistically create the tables;
                will cause background errors being logged if they already exist,
                but is practical to retain existing data across runs (or create as needed) -->
            <property name="jakarta.persistence.schema-generation.database.action" value="drop-and-create"/>

            <property name="jakarta.persistence.validation.mode" value="NONE"/>
        </properties>

    </persistence-unit>
</persistence>

persistence.xml 設定を使用する場合、Hibernate ORM を直接設定することになるため、適切なリファレンスは hibernate.org のドキュメント になります。

これらは Quarkus の application.properties で使用されるプロパティー名と同じではなく、同じデフォルト値も適用されないことに注意してください。

XML マッピング

Quarkus の Hibernate ORM は XML マッピングをサポートしています。 orm.xml 形式 (Jakarta Persistence) または hbm.xml 形式 (Hibernate ORM 固有、非推奨) に従ってマッピングファイルを追加できます。

XML マッピングファイルはビルド時に解析されます。

META-INF/orm.xml ファイルがクラスパスに存在する場合、それは常にデフォルトで含まれます。

それが望ましくない場合は、 quarkus.hibernate-orm.mapping-files = no-file または <mapping-file>no-file</mapping-file> を使用してください。

外部プロジェクトや jar でのエンティティーの定義

Quarkus の Hibernate ORM は、エンティティーに対するコンパイル時のバイトコード強化に依存しています。Quarkus アプリケーションをビルドするのと同じプロジェクトでエンティティーを定義すれば、すべてが正常に動作します。

エンティティーが外部プロジェクトや jar にある場合は、空の META-INF/beans.xml ファイルを追加することで、その jar が Quarkus アプリケーションライブラリーとして扱われるようにすることができます。

これにより、Quarkus はエンティティーが現在のプロジェクト内にあるかのように、エンティティーのインデックス作成と強化を行うことができます。

開発モードでの Hibernate ORM

Quarkus の開発モードは、フロントエンドやサービスとデータベースアクセスを組み合わせるアプリケーションにとって非常に便利です。

それを最大限に活用するための、いくつかの一般的なアプローチがあります。

1 つ目の選択肢は、 quarkus.hibernate-orm.schema-management.strategy=drop-and-createimport.sql と併用することです。

そうすることで、アプリケーション (特にエンティティー) に変更が加えられるたびにデータベーススキーマが適切に再作成され、 import.sql に保存されたデータフィクスチャを使用してゼロからデータが再投入されます。これは環境を完全に制御するのに最適であり、Quarkus のライブリロードモードと組み合わせることで真価を発揮します。エンティティーの変更や import.sql への変更が即座に反映され、アプリケーションを再起動することなくスキーマが更新されます。

デフォルトでは、 dev および test モードにおいて、Hibernate ORM は起動時に (存在すれば) /import.sql ファイル内の SQL 文を読み込んで実行します。 application.propertiesquarkus.hibernate-orm.sql-load-script プロパティーを変更することでファイル名を変更できます。また、実行対象の SQL 文を含むファイルのみを格納した .zip ファイルを同様の方法で提供することも可能です。

2 つ目のアプローチは、 quarkus.hibernate-orm.schema-management.strategy=update を使用することです。このアプローチは、多くのエンティティー変更を行うが、依然として本番データのコピーで作業する必要がある場合や、特定のデータベースエントリーに基づくバグを再現したい場合に最適です。 update は Hibernate ORM によるベストエフォートの処理であり、データベース構造の変更によるデータ損失など、特定の状況では失敗することがあります。例えば、外部キー制約に違反する構造に変更した場合、Hibernate ORM が処理を断念せざるを得ない場合があります。しかし、開発においては、これらの制限は許容できるものです。

3 つ目のアプローチは、 quarkus.hibernate-orm.schema-management.strategy=none を使用することです。このアプローチは、本番データのコピーを使用して作業しているが、スキーマの進化を完全に制御したい場合に最適です。あるいは、 FlywayLiquibase のようなデータベーススキーマ移行ツールを使用している場合です。

このアプローチでは、エンティティーに変更を加える際にデータベーススキーマを適宜修正する必要があります。また、 validate を使用して、Hibernate にスキーマが期待通りであるか検証させることもできます。

本番環境では quarkus.hibernate-orm.schema-management.strategydrop-and-createupdate を使用しないでください。

これらのアプローチは、Quarkus の設定プロファイルと組み合わせることで非常に強力になります。異なる 設定プロファイル を定義して、環境に応じて異なる動作を選択できます。これにより、現在必要な開発スタイルに合わせて、Hibernate ORM プロパティーのさまざまな組み合わせを定義できるため、非常に便利です。

application.properties
%dev.quarkus.hibernate-orm.schema-management.strategy = drop-and-create
%dev.quarkus.hibernate-orm.sql-load-script = import-dev.sql

%dev-with-data.quarkus.hibernate-orm.schema-management.strategy = update
%dev-with-data.quarkus.hibernate-orm.sql-load-script = no-file

%prod.quarkus.hibernate-orm.schema-management.strategy = none
%prod.quarkus.hibernate-orm.sql-load-script = no-file

カスタムプロファイルを使用して開発モードを開始できます。

コマンドラインインタフェース
quarkus dev -Dquarkus.profile=dev-with-data
Maven
./mvnw quarkus:dev -Dquarkus.profile=dev-with-data
Gradle
./gradlew --console=plain quarkusDev -Dquarkus.profile=dev-with-data

本番モードでの Hibernate ORM

Quarkus にはデフォルトのプロファイル ( dev , test , prod ) が付属しています。また、独自のカスタムプロファイルを追加して、さまざまな環境 ( staging , prod-us など) を記述することも可能です。

Hibernate ORM Quarkus エクステンションは、開発モードとテストモードにおいて、他の環境とは異なるデフォルト設定をいくつか適用します。

  • dev および test 以外のすべてのプロファイルでは、 quarkus.hibernate-orm.sql-load-scriptno-file に設定されます。

application.properties で明示的にオーバーライドすることも可能ですが (例: %prod.quarkus.hibernate-orm.sql-load-script = import.sql )、本番環境で誤ってデータベースを上書きしてしまうことを防ぐための仕様です。

そういえば、本番環境でデータベーススキーマを削除しないように注意してください。設定ファイルに以下を追加しましょう。

application.properties
%prod.quarkus.hibernate-orm.schema-management.strategy = none
%prod.quarkus.hibernate-orm.sql-load-script = no-file

Flyway 統合

スキーマ管理のための Flyway への自動移行

開発モードでの実行時に Flyway エクステンション がインストールされている場合、Quarkus は Hibernate ORM によって自動生成されたスキーマを使用して Flyway 設定を簡単に初期化する方法を提供します。これは、Hibernate を使用して迅速にスキーマをセットアップできる初期開発フェーズから、Flyway を使用してスキーマ変更を管理する本番フェーズへの移行を容易にすることを目的としています。

この機能を使用するには、 quarkus-flyway エクステンションがインストールされている状態で Dev UI を開き、 Flyway ペインの Datasources リンクをクリックします。 Create Initial Migration ボタンを押すと、以下が実行されます。

  • db/migration/V1.0.0__{appname}.sql ファイルが作成されます。これには、Hibernate がスキーマ生成のために実行している SQL が含まれます。

  • quarkus.flyway.baseline-on-migrate が設定され、Flyway がベースラインテーブルを自動的に作成するように指示します。

  • quarkus.flyway.migrate-at-start が設定され、アプリケーションの起動時に Flyway が自動的にマイグレーションを適用するように指示します。

  • %dev.quarkus.flyway.clean-at-start および %test.quarkus.flyway.clean-at-start が設定され、開発/テストモードでのリロード後に DB をクリーンアップします。

このボタンは Flyway を素早く使い始めるための便利な機能に過ぎません。本番環境でどのようにデータベーススキーマを管理するかを決定するのはユーザー自身です。特に migrate-at-start 設定は、すべての環境に適しているとは限りません。

エンティティーの変更による増分マイグレーション

最初のマイグレーションが作成された後、Quarkus は更新されたエンティティーモデルからドラフトマイグレーションを派生させることができるため、変更ごとにベースラインを手書きする必要はありません。新しいマイグレーションを作成するには、Dev UI の Flyway ペインにある Generate Migration File ボタンをクリックします。

提案されたスクリプトは必ず確認してください。Quarkus はエンティティーからスキーマの変更を推測しますが、ドメイン固有のデータ移動、並行性の考慮事項、および高度なインデックス戦略には依然として人間の判断が必要です。

生成されるマイグレーションファイルは以下のパターンに従います。

  • メジャーバージョンは、プロジェクト内に存在する最後のマイグレーションから抽出されます。

  • マイナーバージョンは、生成時の現在のタイムスタンプになります。

オフライン起動

デフォルトでは、Hibernate は起動時にデータベースへの接続を試み、メタデータを取得します。これは、たとえばスキーマの検証や一時テーブルの作成に役立ち、起動プロセスをよりスムーズでユーザーフレンドリーなものにします。

ただし、Kubernetes クラスター内のコンテナーで Quarkus アプリケーションを実行する場合など、特定の環境では、この接続が不可能な場合があります。たとえば、アプリケーションが特定のポッドで実行され、データベースが別のポッドで実行されている場合、起動時にデータベースに到達できない可能性があります。これに対処するために、Quarkus は Hibernate がアプリケーションの起動中にデータベースへの接続をスキップできるようにする「オフライン起動」モードを提供しています。

オフライン起動を使用する場合、アプリケーションが起動する前に、データベーススキーマが正しく作成されていることを確認することが重要です。

データベーススキーマの作成やマイグレーションには、 FlywayLiquibase 、またはカスタムセットアップを利用できますが、当然ながらデータベースにアクセス可能なタイミングで行う必要があります。特に Flyway の migrate-at-start オプションは、データベースに到達できない場合、アプリケーションの起動時に失敗します。

オフライン起動を有効にするには、以下の設定プロパティーを設定します。

application.properties
quarkus.hibernate-orm.database.start-offline=true

次のような追加のプロパティーを使用して、特定のデータベースに合わせてダイアレクトの動作を微調整することもできます。

application.properties
quarkus.hibernate-orm."offline".dialect.mariadb.bytes-per-character=1
quarkus.hibernate-orm."offline".dialect.mariadb.no-backslash-escapes=true
quarkus.hibernate-orm."offline".dialect.mariadb.storage-engine=InnoDB (1)
quarkus.hibernate-orm."inventory".dialect.mysql.storage-engine=MyISAM (2)
1 offline 永続化ユニットの MariaDB ダイアレクト用のストレージエンジンを設定します。
2 永続化ユニットごとに異なるストレージエンジンを使用できます。

利用可能なプロパティーの詳細については、 Hibernate ORM の設定リファレンス セクションを参照してください。

キャッシング

同じエンティティーを頻繁に読み取るアプリケーションでは、Hibernate ORM の L2 キャッシュを有効にすることでパフォーマンスを向上させることができます。

エンティティーのキャッシュ

L2 キャッシュを有効にするには、キャッシュしたいエンティティーを @jakarta.persistence.Cacheable でマークします。

@Entity
@Cacheable
public class Country {
    int dialInCode;
    // ...
}

エンティティーに @Cacheable アノテーションが付与されている場合、コレクションや他のエンティティーへのリレーションを除くすべてのフィールド値がキャッシュされます。

これは、データベースに問い合わせることなくエンティティーをロードできることを意味しますが、ロードされたエンティティーがデータベースの最新の変更を反映していない可能性があることに注意してください。

コレクションとリレーションのキャッシュ

コレクションとリレーションをキャッシュするには、個別にアノテーションを付ける必要があります。この場合、Hibernate 固有の @org.hibernate.annotations.Cache を使用し、 CacheConcurrencyStrategy も指定する必要があります。

package org.acme;

@Entity
@Cacheable
public class Country {
    // ...

    @OneToMany
    @Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
    List<City> cities;

    // ...
}

クエリーのキャッシュ

クエリーも L2 キャッシュの恩恵を受けることができます。キャッシュされたクエリー結果を即座に呼び出し元に返すことができるため、データベースでのクエリー実行を回避できます。

結果が最新の変更を反映していない可能性があることに注意してください。

クエリーをキャッシュするには、 Query インスタンスでキャッシュ可能としてマークします。

Query query = ...
query.setHint("org.hibernate.cacheable", Boolean.TRUE);

NamedQuery がある場合は、その定義 (通常はエンティティー上) で直接キャッシュを有効にすることができます。

@Entity
@NamedQuery(name = "Fruits.findAll",
      query = "SELECT f FROM Fruit f ORDER BY f.name",
      hints = @QueryHint(name = "org.hibernate.cacheable", value = "true") )
public class Fruit {
   ...

以上です。キャッシュ技術はすでに Quarkus に統合されており、デフォルトで有効になっているため、どれをキャッシュしても安全かを設定するだけで十分です。

キャッシュ領域の調整

キャッシュは、データの異なる部分を分離するために別々の領域にデータを保存します。これらの領域には名前が割り当てられ、各領域を独立して設定したり、統計を監視したりするのに役立ちます。

デフォルトでは、エンティティーは完全修飾名にちなんだ名前の領域 (例: org.acme.Country ) にキャッシュされます。

コレクションは、その所有者エンティティーの完全修飾名とコレクションフィールド名を # 文字で区切った名前の領域 (例: org.acme.Country#cities ) にキャッシュされます。

すべてのキャッシュされたクエリーは、デフォルトでは default-query-results-region という専用の単一領域に保持されます。

すべての領域は、デフォルトでサイズと時間によって制限されています。デフォルト値は、最大エントリ数が 10000 、最大アイドル時間が 100 秒です。

各領域のサイズは、 quarkus.hibernate-orm.cache."<region_name>".memory.object-count プロパティーを使用してカスタマイズできます ( <region_name> を実際の領域名に置き換えてください)。

最大アイドル時間を設定するには、 quarkus.hibernate-orm.cache."<region_name>".expiration.max-idle プロパティーを介して期間を指定します ( <region_name> は実際の領域名に置き換え、期間の形式については後述の注意を参照してください)。

領域名にドットが含まれている場合、二重引用符は必須です。例:

quarkus.hibernate-orm.cache."org.acme.MyEntity".memory.object-count=1000

期間の値を書くには、標準の java.time.Duration フォーマットを使います。 詳細は Duration#parse() javadoc を参照してください。

数字で始まる簡略化した書式を使うこともできます:

  • 数値のみの場合は、秒単位の時間を表します。

  • 数値の後に ms が続く場合は、ミリ秒単位の時間を表します。

その他の場合は、簡略化されたフォーマットが解析のために java.time.Duration フォーマットに変換されます:

  • 数値の後に hms が続く場合は、その前に PT が付けられます。

  • 数値の後に d が続く場合は、その前に P が付けられます。

キャッシュの制限

Quarkus で提供されているキャッシュ技術は、現在は極めて初歩的で限定的なものです。

開発チームは、何もないよりは、たとえ一部であってもキャッシュ機能がある方が良いと考えました。今後のリリースで、より優れたキャッシュソリューションが統合されることを期待してください。この分野での協力やフィードバックは大歓迎です。

これらのキャッシュはローカルに保持されるため、他のアプリケーションによって永続ストアに変更が加えられても、無効化されたり更新されたりすることはありません。

また、(Kubernetes/OpenShift 上のクラスターなどで) 同じアプリケーションを複数実行している場合、アプリケーションの個々のコピーにあるキャッシュは同期されません。

これらの理由から、キャッシュを有効にすることが適切なのは、特定の前提条件を満たす場合に限られます。決して変更されないエンティティー、コレクション、およびクエリーのみをキャッシュすることを強く推奨します。あるいは、そのようなエンティティーが変更され、古いデータが読み取られたとしても、アプリケーションの動作に影響を与えない場合に限ります。

このアドバイスに従うことで、アプリケーションは L2 キャッシュから最高のパフォーマンスを引き出しつつ、予期せぬ動作を回避できます。

不変データに加え、特定のコンテキストにおいては、可変データに対するキャッシュの有効化が許容される場合があります。これは、頻繁に読み込まれ、ある程度の古さが許容される特定のエンティティーにおいて必要なトレードオフとなる可能性があります。この「許容される古さ」は、エビクションプロパティーを設定することで調整できます。ただし、これは推奨されず、データに予期せぬ影響を与える可能性があるため、細心の注意を払って行う必要があります。

可変データのキャッシュを有効にするよりも、理想的にはクラスター化されたキャッシュを使用する方が優れた解決策となります。しかし、現時点では Quarkus はそのような実装を提供していません。このニーズを開発チームが考慮できるよう、お気軽にご連絡ください。

最後に、 hibernate.cache.use_second_level_cachefalse に設定することで、L2 キャッシュをグローバルに無効化できます。これは persistence.xml 設定ファイルで指定する必要がある設定です。

L2 キャッシュが無効になると、すべてのキャッシュアノテーションは無視され、すべてのクエリーはキャッシュを無視して実行されます。これは通常、問題の診断にのみ役立ちます。

Hibernate Envers

Hibernate ORM の Envers エクステンションは、エンティティークラスに対する簡単な監査およびバージョン管理ソリューションを提供することを目的としています。

Quarkus において、Envers には専用のエクステンション io.quarkus:quarkus-hibernate-envers があります。プロジェクトにこれを追加するだけで使用を開始できます。

Hibernate Envers を有効にするための追加の依存関係
    <!-- Add the Hibernate Envers extension -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-hibernate-envers</artifactId>
    </dependency>

現時点では、このエクステンションは追加の設定プロパティーを公開していません。

Hibernate Envers に関する詳細は、 hibernate.org/orm/envers/ を参照してください。

Hibernate Spatial

Hibernate ORM の Spatial エクステンションは、地理データの保存およびクエリー機能に対する、標準化されたクロスデータベースインターフェースを提供します。

Hibernate Spatial を使用するには、単にプロジェクトに依存関係を追加するだけです。

Hibernate Spatial を有効にするための追加の依存関係
    <!-- Add the Hibernate Spatial module -->
    <dependency>
        <groupId>org.hibernate.orm</groupId>
        <artifactId>hibernate-spatial</artifactId>
    </dependency>

依存関係のバージョンは Quarkus によって管理されるため、明示的に指定する必要はありません。

Spatial に関するすべての情報は、Hibernate ユーザーガイドに記載されています。 Hibernate ORM Spatial

メトリクス

Micrometer は、 Hibernate ORM が実行時に収集するメトリクスを公開できます。 /q/metrics エンドポイントで Hibernate メトリクスの公開を有効にするには、プロジェクトがメトリクスエクステンションに依存していることを確認し、設定プロパティー quarkus.hibernate-orm.metrics.enabledtrue に設定してください。

制限事項とその他の注意事項

Quarkus は使用するライブラリーを変更しません。このルールは Hibernate ORM にも適用されます。このエクステンションを使用する場合、ほとんどの場合、元のライブラリーを使用するのと同様の体験が得られます。

同じコードを共有していますが、Quarkus は一部のコンポーネントを自動的に設定し、いくつかの拡張ポイントにカスタム実装を注入します。これは透過的で有用なはずですが、Hibernate のエキスパートであれば、何が行われているかを知りたいかもしれません。

ビルド時の自動拡張

Hibernate ORM は、ビルド時に拡張されたエンティティーを使用できます。通常、これは必須ではありませんが、便利であり、アプリケーションのパフォーマンスを向上させます。

通常、Hibernate Enhancement プラグインを含めるためにビルドスクリプトを調整する必要がありますが、Quarkus では拡張ステップがアプリケーションのビルドと分析に統合されているため、その必要はありません。

拡張機能を使用しているため、エンティティーでの clone() メソッドの使用は現在サポートされていません。これは、そのエンティティー固有のいくつかの拡張固有フィールドも複製してしまうためです。

この制限は将来的に解消される可能性があります。

自動統合

トランザクションマネージャーの統合

セットアップは不要です。Quarkus は自動的に Narayana Transaction Manager への参照を注入します。この依存関係は Hibernate ORM エクステンションの推移的依存関係として自動的に含まれます。すべての設定は任意です。詳細は Quarkus でのトランザクションの使用 を参照してください。

コネクションプール

選択する必要もありません。Quarkus は自動的に Agroal コネクションプールを含みます。上記の例のようにデータソースを設定すれば、Hibernate ORM が Agroal を使用するようにセットアップされます。このコネクションプールの詳細は Quarkus - データソース を参照してください。

L2 キャッシュ

前述の キャッシングセクション で説明したように、実装を選択する必要はありません。 Infinispan および Caffeine の技術に基づく適切な実装が Hibernate ORM エクステンションの推移的依存関係として含まれており、ビルド中に自動的に統合されます。

制限事項

クラスパス内に重複ファイルがある場合の XML マッピング

XML マッピング ファイルは、一意のパスを持つことが期待されます。

実際、クラスパス内に重複した XML マッピングファイルが存在し得るのは、非常に特殊なシナリオに限られます。たとえば、2 つの JAR に META-INF/orm.xml ファイルが含まれている場合 (パスは全く同じだが異なる JAR にある場合)、マッピングファイルパス META-INF/orm.xml は、 その META-INF/orm.xml ファイルと同じ JAR 内の persistence.xml からしか参照できません。

JMX

管理 Bean は GraalVM ネイティブイメージでは動作しません。そのため、ネイティブイメージへのコンパイル時、統計や管理操作を JMX Bean に登録する Hibernate の機能は無効になります。ネイティブイメージが JMX サポートを実装することは目標ではないため、この制限はおそらく恒久的なものです。これらのメトリクスはすべて他の方法でアクセスできます。

JACC 統合

GraalVM ネイティブイメージのビルド時、JACC はネイティブモードでは利用できず、有用でもないため、Hibernate ORM の JACC 統合機能は無効になります。

Session の ThreadLocal コンテキストへのバインド

Hibernate ORM の ThreadLocalSessionContext ヘルパーは、サポートが実装されていないため使用できません。Quarkus は標準で CDI サポートを提供しているため、インジェクションまたはプログラムによる CDI ルックアップがより優れたアプローチとなります。また、この機能はリアクティブコンポーネントや最新のコンテキスト伝播技術との親和性が低いため、このレガシー機能に将来性はないと考えています。どうしても ThreadLocal にバインドする必要がある場合は、独自のコードで実装するのは簡単であるはずです。

JNDI

JNDI 技術は、異なるコンポーネントを統合するために他のランタイムで一般的に使用されています。よくあるユースケースは、Java Enterprise サーバーで TransactionManager と Datasource コンポーネントを名前にバインドし、Hibernate ORM がそれらのコンポーネントを名前でルックアップするように構成することです。しかし Quarkus では、コンポーネントが直接インジェクションされるためこのユースケースは当てはまらず、JNDI サポートは不要なレガシーとなります。JNDI の予期せぬ使用を避けるための予防措置として、Quarkus の Hibernate ORM エクステンションでは JNDI サポート全体が無効化されています。これはセキュリティー上の予防策であり、最適化でもあります。

その他の注目すべき相違点

import.sql のフォーマット

データベースをセットアップするために import.sql をインポートする際、Quarkus は Hibernate ORM を再構成し、各ステートメントをセミコロン ( ; ) で終了させる必要があることに注意してください。Hibernate のデフォルトは 1 行 1 ステートメントであり、改行以外の終端文字を必要としません。既存のスクリプトを再利用する場合は、 ; 終端文字を使用するようにスクリプトを変換することを忘れないでください。これにより、複数行のステートメントや人間が読みやすいフォーマットが可能になります。

Panache による Hibernate ORM の簡素化

Hibernate ORM with Panache エクステンションは、アクティブレコードスタイルのエンティティー (およびリポジトリー) を提供することで Hibernate ORM の使用を容易にし、Quarkus においてエンティティーを簡単に、楽しく書けるようにすることに重点を置いています。

データソースの設定

データソースの設定は極めてシンプルですが、技術的には Quarkus 用の Agroal コネクションプールエクステンションによって実装されているため、別のガイドで説明されています。

詳細は Quarkus - データソース を参照してください。

マルチテナンシー

「マルチテナンシーという用語は、一般にソフトウェア開発において、アプリケーションの単一の実行インスタンスが複数のクライアント (テナント) に同時にサービスを提供するアーキテクチャーを指すために適用されます。これは SaaS ソリューションで非常によく見られます。さまざまなテナントに関する情報 (データ、カスタマイズなど) を分離することは、これらのシステムにおける特有の課題です。これには、データベースに保存されている各テナントが所有するデータが含まれます」( Hibernate ユーザーガイド )。

Quarkus は現在、 独立したデータベース アプローチ、 独立したスキーマ アプローチ、および ディスクリミネーター アプローチをサポートしています。

マルチテナンシーの実例を確認するには、 hibernate-orm-multi-tenancy-schema-quickstart または hibernate-orm-multi-tenancy-database-quickstart をチェックしてください。

アプリケーションの記述

まず /{tenant} エンドポイントの実装から始めましょう。以下のソースコードからわかるように、これは単なる通常の Jakarta REST リソースです。

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

@ApplicationScoped
@Path("/{tenant}")
public class FruitResource {

    @Inject
    EntityManager entityManager;

    @GET
    @Path("fruits")
    public Fruit[] getFruits() {
        return entityManager.createNamedQuery("Fruits.findAll", Fruit.class)
                .getResultList().toArray(new Fruit[0]);
    }

}

受信リクエストからテナントを解決し、特定のテナント構成にマッピングするには、 io.quarkus.hibernate.orm.runtime.tenant.TenantResolver インターフェースの実装を作成する必要があります。

import jakarta.enterprise.context.ApplicationScoped;

import io.quarkus.hibernate.orm.runtime.tenant.TenantResolver;
import io.vertx.ext.web.RoutingContext;

@PersistenceUnitExtension (1)
@RequestScoped (2)
public class CustomTenantResolver implements TenantResolver {

    @Inject
    RoutingContext context;

    @Override
    public String getDefaultTenantId() {
        return "base";
    }

    @Override
    public String resolveTenantId() {
        String path = context.request().path();
        String[] parts = path.split("/");

        if (parts.length == 0) {
            // resolve to default tenant config
            return getDefaultTenantId();
        }

        return parts[1];
    }

}
1 TenantResolver の実装に @PersistenceUnitExtension 修飾子を付与し、デフォルトの永続化ユニットで使用されるべきであることを Quarkus に伝えます。

名前付き永続化ユニット の場合は、 @PersistenceUnitExtension("nameOfYourPU") を使用してください。

2 テナントの解決は受信リクエストに依存するため、この Bean は @RequestScoped に設定されます。

上記の実装では、テナントはリクエストパスから解決されます。テナントが推測できない場合は、デフォルトのテナント識別子が返されます。

OIDC マルチテナンシー も使用しており、OIDC と Hibernate ORM のテナント ID が同じである場合は、以下の例のように RoutingContext 属性から OIDC テナント ID を取得できます。

import io.quarkus.hibernate.orm.runtime.tenant.TenantResolver;
import io.quarkus.oidc.runtime.OidcUtils;
import io.vertx.ext.web.RoutingContext;

@PersistenceUnitExtension
@RequestScoped
public class CustomTenantResolver implements TenantResolver {

    @Inject
    RoutingContext context; (1)
    ...
    @Override
    public String resolveTenantId() {
        // OIDC has saved the tenant id as the RoutingContext attribute:
        return context.get(OidcUtils.TENANT_ID_ATTRIBUTE);
    }
}
1 Hibernate の TenantResolver が、スケジューラーからのデータベースクエリー時など、アクティブな HTTP リクエストがない場合にもテナントを解決する場合、 RoutingContext CDI Bean は利用できません。代わりに io.quarkus.vertx.http.runtime.CurrentVertxRequest CDI Bean をインジェクションし、この Bean から RoutingContext を取得してください。

アプリケーションの設定

一般に、Hibernate ORM のデータベース生成機能をマルチテナンシー設定と併用することはできません。したがって、この機能を無効にし、スキーマごとにテーブルが作成されるようにする必要があります。以下のセットアップでは、 Flyway エクステンションを使用してこの目的を達成します。

SCHEMA アプローチ

すべてのテナントに対して同じデータソースが使用され、そのデータソース内のテナントごとにスキーマを作成する必要があります。

MariaDBやMySQLなどの一部のデータベースは、デフォルトではデータベーススキーマをサポートしていません。これらの場合、以下のいずれかを行います。 1. スキーマをサポートするように JDBC ドライバーを構成する。 MySQL Connector/J の場合は、 quarkus.datasource.jdbc.additional-jdbc-properties."databaseTerm"=SCHEMA または quarkus.datasource."datasource-name".jdbc.additional-jdbc-properties."databaseTerm"=SCHEMA を使用します。 MariaDB Connector/J の場合は、 quarkus.datasource.jdbc.additional-jdbc-properties."useCatalogTerm"=SCHEMA または quarkus.datasource."datasource-name".jdbc.additional-jdbc-properties."useCatalogTerm"=SCHEMA を使用します。

および 2. DATABASE アプローチ にフォールバックする。

quarkus.hibernate-orm.schema-management.strategy=none (1)

quarkus.hibernate-orm.multitenant=SCHEMA (2)

quarkus.datasource.db-kind=postgresql (3)

quarkus.flyway.schemas=base,mycompany (4)
quarkus.flyway.locations=classpath:schema
quarkus.flyway.migrate-at-start=true

%prod.quarkus.datasource.username=quarkus_test
%prod.quarkus.datasource.password=quarkus_test
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/quarkus_test
1 スキーママルチテナンシーでは Hibernate ORM によるサポートがないため、スキーマ生成を無効にします。代わりに Flyway を使用します。詳細は後述します。
2 スキーママルチテナンシーを有効にします。

ここではデフォルトのデータソースを使用していますが、 こちら の手順に従って名前付きデータソースを使用することも可能です。

3 データソースを設定します
4 このケースでは Hibernate ORM によるスキーマ生成がサポートされていないため、データベース初期化のために Flyway を構成します。

構成されたフォルダー src/main/resources/schema に作成される Flyway SQL ( V1.0.0__create_fruits.sql ) の例です。

CREATE SEQUENCE base.fruit_seq INCREMENT BY 50; -- 50 is quarkus default
CREATE TABLE base.fruit
(
    id   INT,
    name VARCHAR(40)
);
INSERT INTO base.fruit(id, name) VALUES (1, 'Cherry');
INSERT INTO base.fruit(id, name) VALUES (2, 'Apple');
INSERT INTO base.fruit(id, name) VALUES (3, 'Banana');
ALTER SEQUENCE base.fruit_seq RESTART WITH 4;

CREATE SEQUENCE mycompany.fruit_seq INCREMENT BY 50; -- 50 is quarkus default
CREATE TABLE mycompany.fruit
(
  id   INT,
  name VARCHAR(40)
);
INSERT INTO mycompany.fruit(id, name) VALUES (1, 'Avocado');
INSERT INTO mycompany.fruit(id, name) VALUES (2, 'Apricots');
INSERT INTO mycompany.fruit(id, name) VALUES (3, 'Blackberries');
ALTER SEQUENCE mycompany.fruit_seq RESTART WITH 4;

DATABASE アプローチ

テナントごとに、 TenantResolver によって返されるものと同じ識別子を持つ名前付きデータソースを作成する必要があります。

このアプローチでは、同じ永続化ユニットで使用されるすべてのデータソースが、同じベンダー (同じ db-kind ) およびバージョンのデータベースを指していることを前提としています。

不一致は検出されず、予測不可能な動作を引き起こす可能性があります。

データソースのリストはビルド時に定義されるため、このアプローチではテナントの リストビルド時に固定 されます。実行時にテナントのリストを変更する必要がある場合は、 プログラムでテナント接続を解決 する必要があります。

quarkus.hibernate-orm.schema-management.strategy=none (1)

quarkus.hibernate-orm.multitenant=DATABASE (2)
quarkus.hibernate-orm.datasource=base (3)

# Default tenant 'base'
quarkus.datasource.base.db-kind=postgresql (4)
quarkus.flyway.base.locations=classpath:database/base (5)
quarkus.flyway.base.migrate-at-start=true
%prod.quarkus.datasource.base.username=base
%prod.quarkus.datasource.base.password=base
%prod.quarkus.datasource.base.jdbc.url=jdbc:postgresql://localhost:5432/base

# Tenant 'mycompany'
quarkus.datasource.mycompany.db-kind=postgresql (6)
quarkus.flyway.mycompany.locations=classpath:database/mycompany (7)
quarkus.flyway.mycompany.migrate-at-start=true
%prod.quarkus.datasource.mycompany.username=mycompany
%prod.quarkus.datasource.mycompany.password=mycompany
%prod.quarkus.datasource.mycompany.jdbc.url=jdbc:postgresql://localhost:5433/mycompany
1 データベースマルチテナンシーでは Hibernate ORM によるサポートがないため、スキーマ生成を無効にします。代わりに Flyway を使用します。詳細は後述します。
2 データベースマルチテナンシーを有効にします。
3 永続化ユニット用のデータソースを選択します。

これは、Quarkus が使用すべき Hibernate ORM ダイアレクトを決定できるようにするためだけのものです。詳細は このセクション を参照してください。

4 1 つのテナント base 用に データソースを設定 します。
5 このケースでは Hibernate ORM によるスキーマ生成がサポートされていないため、テナント base のデータベース初期化のために Flyway を構成します。
6 別のテナントの データソースを設定 します。

さらに多くのテナントが存在する可能性もありますが、ここでは 2 つに留めます。

7 このケースでは Hibernate ORM によるスキーマ生成がサポートされていないため、テナント mycompany のデータベース初期化のために Flyway を構成します。

構成されたフォルダー src/main/resources/database に作成される Flyway SQL ファイルの例です。

テナント base のスキーマ ( src/main/resources/database/base/V1.0.0__create_fruits.sql )。

CREATE SEQUENCE fruit_seq INCREMENT BY 50; -- 50 is quarkus default
CREATE TABLE fruit
(
    id   INT,
    name VARCHAR(40)
);
INSERT INTO fruit(id, name) VALUES (1, 'Cherry');
INSERT INTO fruit(id, name) VALUES (2, 'Apple');
INSERT INTO fruit(id, name) VALUES (3, 'Banana');
ALTER SEQUENCE fruit_seq RESTART WITH 4;

テナント mycompany のスキーマ ( src/main/resources/database/mycompany/V1.0.0__create_fruits.sql )。

CREATE SEQUENCE fruit_seq INCREMENT BY 50; -- 50 is quarkus default
CREATE TABLE fruit
(
  id   INT,
  name VARCHAR(40)
);
INSERT INTO fruit(id, name) VALUES (1, 'Avocado');
INSERT INTO fruit(id, name) VALUES (2, 'Apricots');
INSERT INTO fruit(id, name) VALUES (3, 'Blackberries');
ALTER SEQUENCE fruit_seq RESTART WITH 4;

DISCRIMINATOR アプローチ

すべてのテナントに対してデフォルトのデータソースが使用されます。 @TenantId アノテーションが付与されたフィールドを定義するすべてのエンティティーでは、そのフィールドが自動的に入力され、クエリー時に自動的にフィルタリングされます。

quarkus.hibernate-orm.multitenant=DISCRIMINATOR (1)

quarkus.datasource.db-kind=postgresql (2)

%prod.quarkus.datasource.username=quarkus_test
%prod.quarkus.datasource.password=quarkus_test
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/quarkus_test
1 ディスクリミネーターマルチテナンシーを有効にします。
2 データソースを設定します

プログラムによるテナント接続の解決

サポートしたいさまざまなテナントに対してより動的な構成が必要であり、構成ファイルに多数のエントリーを記載したくない場合は、 io.quarkus.hibernate.orm.runtime.tenant.TenantConnectionResolver インターフェースを使用して接続取得の独自ロジックを実装できます。このインターフェースを実装したアプリケーションスコープの Bean を作成し、 @PersistenceUnitExtension (名前付き永続化ユニットの場合は @PersistenceUnitExtension("nameOfYourPU") ) を付与すると、現在の Quarkus デフォルト実装である io.quarkus.hibernate.orm.runtime.tenant.DataSourceTenantConnectionResolver が置き換えられます。カスタム接続リゾルバーを使用すると、たとえばデータベースからテナント情報を読み取り、それに基づいて実行時にテナントごとの接続を作成することが可能になります。

自動統合 は、プログラムで作成された ConnectionProvider では動作 しません 。これは、他の Quarkus モジュール (例: SmallRye Health ) からの統合を含むこれらすべての統合を、手動で行う必要があることを意味します。

プーリングに Agroal、トランザクションに Narayana という標準的な Quarkus テクノロジーを使用した TenantConnectionResolver の実装例を以下に示します。

@ApplicationScoped
@PersistenceUnitExtension
public class ExampleTenantConnectionResolver implements TenantConnectionResolver {

    private final jakarta.transaction.TransactionManager transactionManager;
    private final TransactionSynchronizationRegistry transactionSynchronizationRegistry;

    public ExampleTenantConnectionResolver(
            TransactionManager transactionManager,
            TransactionSynchronizationRegistry transactionSynchronizationRegistry) {
        this.transactionManager = transactionManager;
        this.transactionSynchronizationRegistry = transactionSynchronizationRegistry;
    }

    @Override
    public ConnectionProvider resolve(String tenantId) {
        // Use your own ConnectionProvider implementation here
        return new YourOwnCustomConnectionProviderImpl(createDatasource(tenantId));
    }

    private AgroalDataSource createDatasource(String tenantId) {
        try {
            final var txIntegration = new NarayanaTransactionIntegration(
                    transactionManager, transactionSynchronizationRegistry, null, false, null);
            // Fetch JDBC URL, username, password & other values from a per-tenant dynamic source
            final var dataSourceConfig = new AgroalDataSourceConfigurationSupplier()
                    .connectionPoolConfiguration(pc -> pc.initialSize(2)
                            .maxSize(10)
                            .minSize(2)
                            .maxLifetime(Duration.of(5, ChronoUnit.MINUTES))
                            .acquisitionTimeout(Duration.of(30, ChronoUnit.SECONDS))
                            .transactionIntegration(txIntegration)
                            .connectionFactoryConfiguration(
                                    cf -> cf.jdbcUrl("jdbc:postgresql://postgres:5432/" + tenantId)
                                            .credential(new NamePrincipal(username))
                                            .credential(new SimplePassword(password))));
            return AgroalDataSource.from(dataSourceConfig.get());
        } catch (SQLException ex) {
            throw new IllegalStateException(
                    "Failed to create a new data source based on the existing datasource configuration", ex);
        }
    }
}

カスタム関数、型、およびマッピング

Hibernate ORM でカスタム SQL 関数や型を登録するには、標準の Hibernate インターフェースを実装できます。

  • org.hibernate.boot.model.FunctionContributor

  • org.hibernate.boot.model.TypeContributor

これらのインターフェースのいずれかを実装したアプリケーションスコープの Bean を作成し、 @PersistenceUnitExtension (名前付き永続化ユニットの場合は @PersistenceUnitExtension("nameOfYourPU") ) アノテーションを付与すると、対応する永続化ユニットに自動的に登録されます。

カスタム関数コントリビューターの例です。

import java.util.List;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.FunctionContributor;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.ReturnableType;
import org.hibernate.sql.ast.tree.expression.SqlAstNodeRenderingMode;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration;
import io.quarkus.hibernate.orm.PersistenceUnitExtension;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
@PersistenceUnitExtension
public class CustomFunctionContributor implements FunctionContributor {

    @Override
    public void contributeFunctions(FunctionContributions functionContributions) {
        functionContributions.getFunctionRegistry().register(
                "addHardcodedSuffix",
                new HardcodedSuffixFunction(
                        functionContributions.getTypeConfiguration(), "_some_suffix"));
    }

    private static final class HardcodedSuffixFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
        private final String suffix;

        private HardcodedSuffixFunction(TypeConfiguration typeConfiguration, String suffix) {
            super("addHardcodedSuffix",
                    StandardArgumentsValidators.exactly(1),
                    StandardFunctionReturnTypeResolvers.invariant(
                            typeConfiguration.getBasicTypeRegistry().resolve(StandardBasicTypes.STRING)),
                    StandardFunctionArgumentTypeResolvers.impliedOrInvariant(typeConfiguration, StandardBasicTypes.STRING)
            );
            this.suffix = suffix;
        }

        @Override
        public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, ReturnableType<?> returnType,
                           SqlAstTranslator<?> walker) {
            sqlAppender.appendSql('(');
            walker.render(sqlAstArguments.get(0), SqlAstNodeRenderingMode.DEFAULT);
            sqlAppender.appendSql(" || '" + suffix + "')");
        }
    }
}

カスタム UserType (例: Boolean を "Y"/"N" にマッピングする) を登録する、カスタムタイプコントリビューターの例です。

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.TypeContributor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.usertype.UserType;
import io.quarkus.hibernate.orm.PersistenceUnitExtension;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
@PersistenceUnitExtension
public class CustomTypeContributor implements TypeContributor {

    @Override
    public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
        // Registers the custom type so it can be used via @Type(value = BooleanYesNoType.class) on your entity property
        typeContributions.getTypeConfiguration()
                .getBasicTypeRegistry()
                .register(new BooleanYesNoType(), "boolean_yes_no");
    }

    public static final class BooleanYesNoType implements UserType<Boolean> {
        @Override
        public int getSqlType() {
            return SqlTypes.VARCHAR;
        }

        @Override
        public Class<Boolean> returnedClass() {
            return Boolean.class;
        }

        @Override
        public Boolean nullSafeGet(ResultSet rs, int position, WrapperOptions options) throws SQLException {
            String value = rs.getString(position);

            if (value == null) {
                return null;
            }

            return "Y".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value);
        }

        @Override
        public void nullSafeSet(PreparedStatement st, Boolean value, int position, WrapperOptions options) throws SQLException {
            if (value == null) {
                st.setNull(position, SqlTypes.VARCHAR);
            } else {
                st.setString(position, value ? "Y" : "N");
            }
        }

        @Override
        public Boolean deepCopy(Boolean value) {
            return value;
        }

        @Override
        public boolean isMutable() {
            return false;
        }
    }
}

インターセプター

適切な修飾子を持つ CDI Bean を定義するだけで、 org.hibernate.InterceptorSessionFactory に割り当てることができます。

@PersistenceUnitExtension (1)
public static class MyInterceptor implements Interceptor, Serializable { (2)
    @Override
    public boolean onLoad(Object entity, Object id, Object[] state, (3)
            String[] propertyNames, Type[] types) {
        // ...
        return false;
    }
}
1 インターセプターの実装に @PersistenceUnitExtension 修飾子を付与し、デフォルトの永続化ユニットで使用されるべきであることを Quarkus に伝えます。

名前付き永続化ユニット の場合は、 @PersistenceUnitExtension("nameOfYourPU") を使用します。

2 必要に応じて org.hibernate.Interceptor のメソッドを実装します。

デフォルトでは、 @PersistenceUnitExtension が付与されたインターセプター Bean はアプリケーションスコープになります。つまり、アプリケーションごとに 1 つのインターセプターインスタンスのみが作成され、すべてのエンティティーマネージャーで再利用されます。このため、インターセプターの実装はスレッドセーフである必要があります。

代わりにエンティティーマネージャーごとに 1 つのインターセプターインスタンスを作成するには、Bean に @Dependent アノテーションを付与します。その場合、インターセプターの実装はスレッドセーフである必要はありません。

Hibernate ORM 自体の制限により、 @Dependent スコープのインターセプターにおける @PreDestroy メソッドは決して呼び出されません。

ステートメントインスペクター

適切な修飾子を持つ CDI Bean を定義するだけで、 org.hibernate.engine.jdbc.spi.StatementInspectorSessionFactory に割り当てることができます。

@PersistenceUnitExtension (1)
public class MyStatementInspector implements StatementInspector { (2)
    @Override
    public String inspect(String sql) {
        // ...
        return sql;
    }
}
1 ステートメントインスペクターの実装に @PersistenceUnitExtension 修飾子を付与し、デフォルトの永続化ユニットで使用されるべきであることを Quarkus に伝えます。

名前付き永続化ユニット の場合は、 @PersistenceUnitExtension("nameOfYourPU") を使用します。

2 org.hibernate.engine.jdbc.spi.StatementInspector を実装します。

JSON/XML のシリアル化/デシリアル化のカスタマイズ

デフォルトでは、Quarkus は利用可能なエクステンションに応じてフォーマットマッパーを自動的に構成しようとします。Jackson (または JSON-B) が利用可能な場合、グローバルに構成された ObjectMapper (または Jsonb ) がシリアル化/デシリアル化操作に使用されます。Jackson と JSON-B の両方が同時に利用可能な場合は、Jackson が優先されます。

Hibernate ORM における JSON および XML のシリアル化/デシリアル化は、 org.hibernate.type.format.FormatMapper を実装し、その実装に適切な修飾子でアノテーションを付けることでカスタマイズできます。

import io.quarkus.hibernate.orm.JsonFormat;
import org.hibernate.type.format.FormatMapper;

@JsonFormat (1)
@PersistenceUnitExtension (2)
public class MyJsonFormatMapper implements FormatMapper { (3)
    @Override
    public <T> T fromString(CharSequence charSequence, JavaType<T> javaType, WrapperOptions wrapperOptions) {
        // ...
    }

    @Override
    public <T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions) {
       // ...
    }
}
1 フォーマットマッパーの実装に @JsonFormat 修飾子を付与し、このマッパーが JSON のシリアル化/デシリアル化に特化したものであることを Quarkus に伝えます。
Jackson のものではなく、 Quarkus 固有の @io.quarkus.hibernate.orm.JsonFormat アノテーションが使用されていることを確認してください。
2 フォーマットマッパーの実装に @PersistenceUnitExtension 修飾子を付与し、デフォルトの永続化ユニットで使用されるべきであることを Quarkus に伝えます。

名前付き永続化ユニット の場合は、 @PersistenceUnitExtension("nameOfYourPU") を使用します。

3 org.hibernate.type.format.FormatMapper を実装します。

カスタム XML フォーマットマッパーの場合は、別の CDI 修飾子を適用する必要があります。

import io.quarkus.hibernate.orm.XmlFormat;
import org.hibernate.type.format.FormatMapper;

@XmlFormat (1)
@PersistenceUnitExtension (2)
public class MyJsonFormatMapper implements FormatMapper { (3)
    @Override
    public <T> T fromString(CharSequence charSequence, JavaType<T> javaType, WrapperOptions wrapperOptions) {
        // ...
    }

    @Override
    public <T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions) {
       // ...
    }
}
1 フォーマットマッパーの実装に @XmlFormat 修飾子を付与し、このマッパーが XML のシリアル化/デシリアル化に特化したものであることを Quarkus に伝えます。
2 フォーマットマッパーの実装に @PersistenceUnitExtension 修飾子を付与し、デフォルトの永続化ユニットで使用されるべきであることを Quarkus に伝えます。

名前付き永続化ユニット の場合は、 @PersistenceUnitExtension("nameOfYourPU") を使用します。

3 org.hibernate.type.format.FormatMapper を実装します。

フォーマットマッパーには、 @PersistenceUnitExtension と、 @JsonFormat または @XmlFormat のいずれかの CDI 修飾子が両方適用されている 必要があります

同じ永続化ユニットに対して複数の JSON (または XML) フォーマットマッパーが登録されていると、曖昧さのために例外が発生します。

バリデーションモードと Hibernate Validator の統合

Hibernate ORM への Hibernate Validator の統合により、以下の機能が利用可能になります。

  • ライフサイクルイベント時のエンティティーバリデーションの実行

  • エンティティーからの制約情報を DDL に適用

Quarkus の観点からは、これは quarkus.hibernate-orm.validation.mode 設定プロパティー によって制御されます。利用可能なバリデーションモードは以下の通りです。

  • auto — デフォルトのオプション。アプリケーションが quarkus-hibernate-validator を使用している場合は callbackddl が同時に有効である場合と同様に動作し、そうでない場合は none として動作します。

  • callback — Hibernate Validator がライフサイクルイベントのバリデーションを実行します。

  • ddl — Hibernate Validator の制約が DDL 操作 で考慮されます。

  • none — Hibernate Validator の統合が無効になります。

対応する Jakarta Validation ルールを持つすべての制約は callback バリデーション中に適用されますが、 ddl モードでは、DDL に影響を与えるために制約のサブセットのみが使用されます。Hibernate Validator のドキュメントに、 利用可能な制約のリスト とそれらが DDL 生成に与える影響が記載されています。

プロパティーにいくつかの制約が適用された単純なエンティティーを考えてみましょう。

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

@Entity
public class MyEntity {
    @Id
    @GeneratedValue
    public long id;

    @NotNull
    @NotEmpty
    @Size(max = 50)
    public String name;

    public String value;
}

ddl モードを有効にした場合、生成されるスキーマには以下の制約が含まれることが期待されます。

create table myentity
(
    id    bigint      not null  primary key,
    name  varchar(50) not null, (1)
    value varchar(255),         (2)
);
1 name カラムには @NotNull 制約があるため not null 制約が付き、値の長さは @Size(max=50) 制約により 50 に制限されます。
2 エンティティの value プロパティーには制約がないため、DDL に追加の制約はありません。また、 255 という長さの制限は、デフォルトの jakarta.persistence.Column#lenght() に由来します。

callback モードでは、 jakarta.validation.ConstraintViolationException がスローされることを期待してください。

try {
    MyEntity entity = new MyEntity();
    entity.setName(veryLongName);
    em.persist(entity);
    em.flush();
} catch (ConstraintViolationException exception) {
    // handle the constraint violations somehow
}

Quarkus には jakarta.validation.ConstraintViolationException 用の組み込み例外マッパーがあるため、これらの例外を明示的に処理することは冗長になる可能性があります。詳細は Hibernate Validator ガイドの REST エンドポイントのバリデーション セクションを参照してください。

静的メタモデルと Jakarta Data

Hibernate ORM の静的メタモデルと Jakarta Data の機能は、両方とも hibernate-processor アノテーションプロセッサーを介して Quarkus で利用可能です。これはアノテーションプロセッサーであるため、ビルドツールで適切に設定する必要があります。

pom.xml
<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <!-- This setting is required for the annotation processor dependencies to be managed by Quarkus.
             More information is available in Maven compiler plugin documentation:
             https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#annotationProcessorPathsUseDepMgmt -->
        <annotationProcessorPathsUseDepMgmt>true</annotationProcessorPathsUseDepMgmt>
        <annotationProcessorPaths>
            <path>
                <groupId>org.hibernate.orm</groupId>
                <artifactId>hibernate-processor</artifactId>
                <!-- Note, no artifact version is required, it's managed by Quarkus.  -->
            </path>
            <!-- other processors that may be required by your app -->
        </annotationProcessorPaths>
        <!-- Other compiler plugin configuration options -->
    </configuration>
</plugin>
build.gradle
// Enforce the version management of your annotation processor dependencies,
// so that there's no need to define an explicit version of the hibernate-processor
annotationProcessor enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
annotationProcessor 'org.hibernate.orm:hibernate-processor'

静的メタモデル

生成された静的メタモデルを使用すると、型安全な方法でクエリーを構築できます。シンプルなエンティティを考えてみましょう。

@Entity
public class MyEntity {
    @Id
    @GeneratedValue
    public Integer id;

    @Column(unique = true)
    public String name;
}

静的メタモデルを使用して作成されたクエリーは、次のようになります。

var builder = session.getCriteriaBuilder();
var criteria = builder.createQuery(MyEntity.class);
var e = criteria.from(MyEntity_.class);
criteria.where(e.get(MyEntity_.name).equalTo(name));
var query = session.createQuery(criteria);
var result = query.list();

静的メタモデルの詳細については、 Jakarta Persistence 仕様 を参照してください。

Jakarta Data

Jakarta Data では、 hibernate-processor アノテーションプロセッサーを配置する以外に、1 つの追加の依存関係を追加する必要があります。

pom.xml
<dependency>
    <groupId>jakarta.data</groupId>
    <artifactId>jakarta.data-api</artifactId>
</dependency>
build.gradle
implementation 'jakarta.data:jakarta.data-api'

この依存関係を追加し、アノテーションプロセッサーを配置すると、次のようにリポジトリーを簡単に作成できます。

@Repository
public interface MyRepository extends CrudRepository<MyEntity, Integer> { (1)

    @Query("select e from MyEntity e where e.name like :name") (2)
    List<MyEntity> findByName(String name);

    @Delete (3)
    void delete(String name);

}
1 CRUD 操作のボイラープレートな定義をスキップするために、利用可能なインターフェース (例: CrudRepositoryBasicRepository) のいずれかを使用できます。
2 パラメーター付きのカスタムクエリーの追加は、 @Query アノテーションにクエリー文字列を提供するのと同様に簡単です。
3 Jakarta Data インターフェースの基本的な CRUD 操作で不十分な場合は、いつでもカスタム操作を追加できます。この例では、名前で MyEntity を削除する削除操作です。

そして、リポジトリーは他の Bean と同様に使用できます。

public class MyEntityResource {

    @Inject
    MyRepository repository;

    @POST
    @Transactional
    public void create(MyEntity entity) {
        repository.insert(entity);
    }

    // ...

}

デフォルト以外の永続化ユニットを操作する場合は、リポジトリーアノテーションの dataStore 属性で、リポジトリーがターゲットとしている永続化ユニット名を指定することを忘れないでください。

@Repository(dataStore = "other") (1)
public interface MyNonDefaultPURepository {
    // ...
}
1 デフォルト以外の永続化ユニットの名前をリポジトリーアノテーションに渡します (この例では other)。

dataStore 属性の詳細については、 @Repository アノテーションの Javadoc を確認してください。

他にどのような機能があるかについては、対応する Hibernate Data Repositories および Jakarta Data ガイドを参照してください。

Jakarta Data リポジトリーのセキュア化

Quarkus Security は、セキュリティーアノテーションを使用して Jakarta Data リポジトリーを保護するための初期サポートを提供します。

メソッドレベルのセキュリティーアノテーションを使用した Jakarta Data リポジトリーの例
@Repository
public interface MyRepository extends CrudRepository<MyEntity, Integer> {

    @RolesAllowed("admin")
    @Delete
    void delete(String name);

}
クラスレベルのセキュリティーアノテーションを使用した Jakarta Data リポジトリーの例
@Authenticated
@Repository
public interface MyRepository extends CrudRepository<MyEntity, Integer> {

    @Delete
    void delete(String name);

}

上記の例では、 MyRepository インターフェースで直接宣言されたメソッドのみが保護されます。 insert などの CrudRepository から継承されたメソッドは、型レベルのアノテーションがアノテーションを付けた型自体にのみ影響するため、保護されません。

現在、型変数やワイルドカードを使用する汎用インターフェースメソッドは、標準のセキュリティーアノテーションでは確実には保護できません。したがって、そのようなメソッドを保護しようとするのではなく、以下に説明する 2 つの代替案のいずれかを使用する必要があります。

型変数を使用した汎用メソッドを持つリポジトリーの例
public interface MyParentRepository<T extends MyEntity> {

    @Find
    Stream<T> findAll(Order<T> order);

}

@Repository
public interface MyRepository extends MyParentRepository<MyEntity> {
}

代替案 1: REST レイヤーの呼び出し元メソッドにセキュリティーアノテーションを適用する。

@Path("my-entity")
public class MyEntityResource {

    @Inject
    MyRepository myRepository;

    @PermissionsAllowed("find-all")
    @GET
    public List<MyEntity> findAll() {
        return myRepository.findAll(Order.by(Sort.asc(MyEntity_.NAME))).toList();
    }

}

代替案 2: リポジトリーインターフェースの型変数 T を具体的な型に置き換える。

@Repository
public interface MyRepository {

    @PermissionsAllowed("find-all")
    @Find
    Stream<MyEntity> findAll(Order<MyEntity> order);

}

Hibernate ORM の設定リファレンス

ビルド時に固定される設定プロパティー - 他のすべての設定プロパティーは実行時にオーバーライド可能

Configuration property

デフォルト

Whether Hibernate ORM is enabled during the build.

If Hibernate ORM is disabled during the build, all processing related to Hibernate ORM will be skipped, but it will not be possible to activate Hibernate ORM at runtime: quarkus.hibernate-orm.active will default to false and setting it to true will lead to an error.

Environment variable: QUARKUS_HIBERNATE_ORM_ENABLED

Show more

boolean

true

Whether Hibernate ORM is working in blocking mode.

Hibernate ORM’s blocking EntityManager/Session/SessionFactory are normally disabled by default if no JDBC datasource is found. You can set this property to false if you want to disable them despite having a JDBC datasource.

Environment variable: QUARKUS_HIBERNATE_ORM_BLOCKING

Show more

boolean

true

If true, Quarkus will ignore any persistence.xml file in the classpath and rely exclusively on the Quarkus configuration.

Environment variable: QUARKUS_HIBERNATE_ORM_PERSISTENCE_XML_IGNORE

Show more

boolean

false

Whether statistics collection is enabled. If 'metrics.enabled' is true, then the default here is considered true, otherwise the default is false.

Environment variable: QUARKUS_HIBERNATE_ORM_STATISTICS

Show more

boolean

Whether session metrics should be appended into the server log for each Hibernate session. This only has effect if statistics are enabled (quarkus.hibernate-orm.statistics). The default is false (which means both statistics and log-session-metrics need to be enabled for the session metrics to appear in the log).

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_SESSION_METRICS

Show more

boolean

Whether metrics are published if a metrics extension is enabled.

Environment variable: QUARKUS_HIBERNATE_ORM_METRICS_ENABLED

Show more

boolean

false

Allow hql queries in the Dev UI page

Environment variable: QUARKUS_HIBERNATE_ORM_DEV_UI_ALLOW_HQL

Show more

boolean

false

Enable or disable access to a Hibernate ORM EntityManager/Session/StatelessSession *when no transaction is active* but a request scope is. When enabled, the corresponding sessions will be read-only. Defaults to enabled for backwards compatibility, but disabling this is recommended, to avoid inconsistent resulsts caused by queries running outside of transactions.

Environment variable: QUARKUS_HIBERNATE_ORM_REQUEST_SCOPED_ENABLED

Show more

boolean

true

quarkus.hibernate-orm."persistence-unit-name".datasource

The name of the datasource which this persistence unit uses.

If undefined, it will use the default datasource.

Environment variable: QUARKUS_HIBERNATE_ORM_DATASOURCE

Show more

string

quarkus.hibernate-orm."persistence-unit-name".packages

The packages in which the entities affected to this persistence unit are located.

Environment variable: QUARKUS_HIBERNATE_ORM_PACKAGES

Show more

list of string

quarkus.hibernate-orm."persistence-unit-name".sql-load-script

Paths to files containing the SQL statements to execute when Hibernate ORM starts.

The files are retrieved from the classpath resources, so they must be located in the resources directory (e.g. src/main/resources).

The default value for this setting differs depending on the Quarkus launch mode:

  • In dev and test modes, it defaults to import.sql. Simply add an import.sql file in the root of your resources directory and it will be picked up without having to set this property. Pass no-file to force Hibernate ORM to ignore the SQL import file.

  • In production mode, it defaults to no-file. It means Hibernate ORM won’t try to execute any SQL import file by default. Pass an explicit value to force Hibernate ORM to execute the SQL import file.

If you need different SQL statements between dev mode, test (@QuarkusTest) and in production, use Quarkus configuration profiles facility.

application.properties
%dev.quarkus.hibernate-orm.sql-load-script = import-dev.sql
%test.quarkus.hibernate-orm.sql-load-script = import-test.sql
%prod.quarkus.hibernate-orm.sql-load-script = no-file

Quarkus supports files with SQL statements or comments spread over multiple lines, or .zip files containing those files. Each SQL statement must be terminated by a semicolon.

Environment variable: QUARKUS_HIBERNATE_ORM_SQL_LOAD_SCRIPT

Show more

list of string

import.sql in dev and test modes ; no-file otherwise

quarkus.hibernate-orm."persistence-unit-name".physical-naming-strategy

Pluggable strategy contract for applying physical naming rules for database object names. Class name of the Hibernate PhysicalNamingStrategy implementation

Environment variable: QUARKUS_HIBERNATE_ORM_PHYSICAL_NAMING_STRATEGY

Show more

string

quarkus.hibernate-orm."persistence-unit-name".implicit-naming-strategy

Pluggable strategy for applying implicit naming rules when an explicit name is not given. Class name of the Hibernate ImplicitNamingStrategy implementation

Environment variable: QUARKUS_HIBERNATE_ORM_IMPLICIT_NAMING_STRATEGY

Show more

string

quarkus.hibernate-orm."persistence-unit-name".mapping-files

XML files to configure the entity mapping, e.g. META-INF/my-orm.xml.

Defaults to META-INF/orm.xml if it exists. Pass no-file to force Hibernate ORM to ignore META-INF/orm.xml.

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_FILES

Show more

list of string

META-INF/orm.xml if it exists; no-file otherwise

quarkus.hibernate-orm."persistence-unit-name".quote-identifiers.strategy

Identifiers can be quoted using one of the available strategies.

Set to none by default, meaning no identifiers will be quoted. If set to all, all identifiers and column definitions will be quoted. Additionally, setting it to all-except-column-definitions will skip the column definitions, which can usually be required when they exist, or else use the option only-keywords to quote only identifiers deemed SQL keywords by the Hibernate ORM dialect.

Environment variable: QUARKUS_HIBERNATE_ORM_QUOTE_IDENTIFIERS_STRATEGY

Show more

noneIdentifiers are not quoted., allAll identifiers are quoted., all-except-column-definitionsAll identifiers, except column definitions, are quoted., only-keywordsOnly keywords will be quoted.

noneIdentifiers are not quoted.

quarkus.hibernate-orm."persistence-unit-name".second-level-caching-enabled

The default in Quarkus is for 2nd level caching to be enabled, and a good implementation is already integrated for you.

Just cherry-pick which entities should be using the cache.

Set this to false to disable all 2nd level caches.

Environment variable: QUARKUS_HIBERNATE_ORM_SECOND_LEVEL_CACHING_ENABLED

Show more

boolean

true

quarkus.hibernate-orm."persistence-unit-name".validation.mode

Defines how the Bean Validation integration behaves.

Environment variable: QUARKUS_HIBERNATE_ORM_VALIDATION_MODE

Show more

list of autoIf a Bean Validation provider is present then behaves as if both ValidationMode#CALLBACK and ValidationMode#DDL modes are configured. Otherwise, same as ValidationMode#NONE., callbackBean Validation will perform the lifecycle event validation., ddlBean Validation constraints will be considered for the DDL operations., noneBean Validation integration will be disabled.

auto

quarkus.hibernate-orm."persistence-unit-name".multitenant

Defines the method for multi-tenancy (DATABASE, NONE, SCHEMA). The complete list of allowed values is available in the Hibernate ORM JavaDoc. The type DISCRIMINATOR is currently not supported. The default value is NONE (no multi-tenancy).

Environment variable: QUARKUS_HIBERNATE_ORM_MULTITENANT

Show more

string

quarkus.hibernate-orm."persistence-unit-name".validate-in-dev-mode

If hibernate is not auto generating the schema, and Quarkus is running in development mode then Quarkus will attempt to validate the database after startup and print a log message if there are any problems.

Environment variable: QUARKUS_HIBERNATE_ORM_VALIDATE_IN_DEV_MODE

Show more

boolean

true

quarkus.hibernate-orm."persistence-unit-name".active

Whether this persistence unit should be active at runtime.

Note that if Hibernate ORM is disabled (i.e. quarkus.hibernate-orm.enabled is set to false), all persistence units are deactivated, and setting this property to true will fail.

Environment variable: QUARKUS_HIBERNATE_ORM_ACTIVE

Show more

boolean

`true` if Hibernate ORM is enabled and there are entity types or an active datasource assigned to the persistence unit; `false` otherwise

quarkus.hibernate-orm."persistence-unit-name".unsupported-properties."full-property-key"

Properties that should be passed on directly to Hibernate ORM. Use the full configuration property key here, for instance quarkus.hibernate-orm.unsupported-properties."hibernate.order_inserts" = true.

Properties set here are completely unsupported: as Quarkus doesn’t generally know about these properties and their purpose, there is absolutely no guarantee that they will work correctly, and even if they do, that may change when upgrading to a newer version of Quarkus (even just a micro/patch version).

Consider using a supported configuration property before falling back to unsupported ones. If none exists, make sure to file a feature request so that a supported configuration property can be added to Quarkus, and more importantly so that the configuration property is tested regularly.

Environment variable: QUARKUS_HIBERNATE_ORM_UNSUPPORTED_PROPERTIES__FULL_PROPERTY_KEY_

Show more

Map<String,String>

quarkus.hibernate-orm."persistence-unit-name".batch-fetch-size

This property is deprecated: fetch should be used to configure fetching properties.

The size of the batches used when loading entities and collections.

-1 means batch loading is disabled.

Environment variable: QUARKUS_HIBERNATE_ORM_BATCH_FETCH_SIZE

Show more

int

16

quarkus.hibernate-orm."persistence-unit-name".max-fetch-depth

This property is deprecated: fetch should be used to configure fetching properties.

The maximum depth of outer join fetch tree for single-ended associations (one-to-one, many-to-one).

A 0 disables default outer join fetching.

Environment variable: QUARKUS_HIBERNATE_ORM_MAX_FETCH_DEPTH

Show more

int

quarkus.hibernate-orm."persistence-unit-name".metadata-builder-contributor

This property is deprecated.

Class name of a custom org.hibernate.boot.spi.MetadataBuilderContributor implementation.

Not all customization options exposed by org.hibernate.boot.MetadataBuilder will work correctly. Stay clear of options related to classpath scanning in particular.

This setting is exposed mainly to allow registration of types, converters and SQL functions.

  • @deprecated Use TypeContributor, FunctionContributor or AdditionalMappingContributor instead.

Environment variable: QUARKUS_HIBERNATE_ORM_METADATA_BUILDER_CONTRIBUTOR

Show more

string

quarkus.hibernate-orm."persistence-unit-name".validation.enabled

This property is deprecated since 3.19: Use mode() instead.

Enables the Bean Validation integration.

Environment variable: QUARKUS_HIBERNATE_ORM_VALIDATION_ENABLED

Show more

boolean

true

quarkus.hibernate-orm."persistence-unit-name".multitenant-schema-datasource

This property is deprecated: Use datasource() instead.

Defines the name of the datasource to use in case of SCHEMA approach. The datasource of the persistence unit will be used if not set.

Environment variable: QUARKUS_HIBERNATE_ORM_MULTITENANT_SCHEMA_DATASOURCE

Show more

string

Database related configuration

デフォルト

When set, attempts to exchange data with the database as the given version of Hibernate ORM would have, on a best-effort basis.

Please note:

  • schema validation may still fail in some cases: this attempts to make Hibernate ORM 6+ behave correctly at runtime, but it may still expect a different (but runtime-compatible) schema.

  • robust test suites are still useful and recommended: you should still check that your application behaves as intended with your legacy schema.

  • this feature is inherently unstable: some aspects of it may stop working in future versions of Quarkus, and older versions will be dropped as Hibernate ORM changes pile up and support for those older versions becomes too unreliable.

  • you should still plan a migration of your schema to a newer version of Hibernate ORM. For help with migration, refer to the Quarkus 3 migration guide from Hibernate ORM 5 to 6.

Environment variable: QUARKUS_HIBERNATE_ORM_DATABASE_ORM_COMPATIBILITY_VERSION

Show more

5.6, latest

latest

quarkus.hibernate-orm."persistence-unit-name".database.charset

The charset of the database.

Used for DDL generation and also for the SQL import scripts.

Environment variable: QUARKUS_HIBERNATE_ORM_DATABASE_CHARSET

Show more

Charset

UTF-8

quarkus.hibernate-orm."persistence-unit-name".database.default-catalog

The default catalog to use for the database objects.

Environment variable: QUARKUS_HIBERNATE_ORM_DATABASE_DEFAULT_CATALOG

Show more

string

quarkus.hibernate-orm."persistence-unit-name".database.default-schema

The default schema to use for the database objects.

Environment variable: QUARKUS_HIBERNATE_ORM_DATABASE_DEFAULT_SCHEMA

Show more

string

quarkus.hibernate-orm."persistence-unit-name".database.version-check.enabled

Whether Hibernate ORM should check on startup that the version of the database matches the version configured on the dialect (either the default version, or the one set through quarkus.datasource.db-version).

This should be set to false if the database is not available on startup.

Environment variable: QUARKUS_HIBERNATE_ORM_DATABASE_VERSION_CHECK_ENABLED

Show more

boolean

`false` if starting offline (see `start-offline`), `true` otherwise

quarkus.hibernate-orm."persistence-unit-name".database.start-offline

Instructs Hibernate ORM to avoid connecting to the database on startup.

When starting offline: * Hibernate ORM will not attempt to create a schema automatically, so it must already be created when the application hits the database for the first time. * Quarkus will not check that the database version matches the one configured at build time.

Environment variable: QUARKUS_HIBERNATE_ORM_DATABASE_START_OFFLINE

Show more

boolean

false

JSON/XML mapping related configuration

デフォルト

How the default JSON/XML format mappers are configured. Only available to mitigate migration from the current Quarkus-preconfigured format mappers (that will be removed in the future version).

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_FORMAT_GLOBAL

Show more

ignore, warn, fail

fail

quarkus.hibernate-orm."persistence-unit-name".mapping.timezone.default-storage

How to store timezones in the database by default for properties of type OffsetDateTime and ZonedDateTime. This default may be overridden on a per-property basis using @TimeZoneStorage. NOTE: Properties of type OffsetTime are https://hibernate.atlassian.net/browse/HHH-16287[not affected by this setting].

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_TIMEZONE_DEFAULT_STORAGE

Show more

nativeStores the timestamp and timezone in a column of type timestamp with time zone. Only available on some databases/dialects; if not supported, an exception will be thrown during static initialization., normalizeDoes not store the timezone, and loses timezone information upon persisting. Instead, normalizes the value\: * upon persisting to the database, to a timestamp in the JDBC timezone set through quarkus.hibernate-orm.jdbc.timezone, or the JVM default timezone if not set. * upon reading back from the database, to the JVM default timezone. Use this to get the legacy behavior of Quarkus 2 / Hibernate ORM 5 or older., normalize-utcDoes not store the timezone, and loses timezone information upon persisting. Instead, normalizes the value to a timestamp in the UTC timezone., columnStores the timezone in a separate column next to the timestamp column. Use @TimeZoneColumn on the relevant entity property to customize the timezone column., autoEquivalent to native if supported, column otherwise., defaultEquivalent to native if supported, normalize-utc otherwise.

defaultEquivalent to native if supported, normalize-utc otherwise.

quarkus.hibernate-orm."persistence-unit-name".mapping.id.optimizer.default

The optimizer to apply to identifier generators whose optimizer is not configured explicitly.

Only relevant for table- and sequence-based identifier generators. Other generators, such as UUID-based generators, will ignore this setting.

The optimizer is responsible for pooling new identifier values, in order to reduce the frequency of database calls to retrieve those values and thereby improve performance.

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_ID_OPTIMIZER_DEFAULT

Show more

pooled-loAssumes the value retrieved from the table/sequence is the lower end of the pool. Upon retrieving value N, the new pool of identifiers will go from N to N + <allocation size> - 1, inclusive., pooledAssumes the value retrieved from the table/sequence is the higher end of the pool. Upon retrieving value N, the new pool of identifiers will go from N - <allocation size> to N + <allocation size> - 1, inclusive. The first value, 1, is handled differently to avoid negative identifiers. Use this to get the legacy behavior of Quarkus 2 / Hibernate ORM 5 or older., noneNo optimizer, resulting in a database call each and every time an identifier value is needed from the generator. Not recommended in production environments\: may result in degraded performance and/or frequent gaps in identifier values.

pooled-loAssumes the value retrieved from the table/sequence is the lower end of the pool. Upon retrieving value N, the new pool of identifiers will go from N to N + <allocation size> - 1, inclusive.

quarkus.hibernate-orm."persistence-unit-name".mapping.duration.preferred-jdbc-type

The preferred JDBC type to use for storing {@link java.time.Duration} values. <p> Can be overridden locally using @JdbcType, @JdbcTypeCode, and similar annotations. <p> Can also specify the name of the SqlTypes constant field, for example, quarkus.hibernate-orm.mapping.type.preferred_jdbc_type=INTERVAL_SECOND.

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_DURATION_PREFERRED_JDBC_TYPE

Show more

string

INTERVAL_SECOND

quarkus.hibernate-orm."persistence-unit-name".mapping.instant.preferred-jdbc-type

The preferred JDBC type to use for storing {@link java.time.Instant} values. <p> Can be overridden locally using @JdbcType, @JdbcTypeCode, and similar annotations. <p> Can also specify the name of the SqlTypes constant field, for example, quarkus.hibernate-orm.mapping.type.preferred_instant_jdbc_type=TIMESTAMP or quarkus.hibernate-orm.mapping.type.preferred_instant_jdbc_type=INSTANT.

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_INSTANT_PREFERRED_JDBC_TYPE

Show more

string

TIMESTAMP

quarkus.hibernate-orm."persistence-unit-name".mapping.boolean.preferred-jdbc-type

The preferred JDBC type to use for storing boolean values. <p> Can be overridden locally using @JdbcType, @JdbcTypeCode, and similar annotations. <p> Can also specify the name of the SqlTypes constant field, for example, quarkus.hibernate-orm.mapping.type.boolean_jdbc_type=BIT.

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_BOOLEAN_PREFERRED_JDBC_TYPE

Show more

string

BOOLEAN

quarkus.hibernate-orm."persistence-unit-name".mapping.uuid.preferred-jdbc-type

The preferred JDBC type to use for storing {@link java.util.UUID} values. <p> Can be overridden locally using @JdbcType, @JdbcTypeCode, and similar annotations. <p> Can also specify the name of the SqlTypes constant field, for example, quarkus.hibernate-orm.mapping.type.uuid_jdbc_type=CHAR.

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_UUID_PREFERRED_JDBC_TYPE

Show more

string

UUID

Dialect related configuration

デフォルト

quarkus.hibernate-orm."persistence-unit-name".dialect

Name of the Hibernate ORM dialect.

For supported databases, this property does not need to be set explicitly: it is selected automatically based on the datasource, and configured using the DB version set on the datasource to benefit from the best performance and latest features.

If your database does not have a corresponding Quarkus extension, you will need to set this property explicitly. In that case, keep in mind that the JDBC driver and Hibernate ORM dialect may not work properly in GraalVM native executables.

For built-in dialects, the expected value is one of the names in the official list of dialects, without the Dialect suffix, for example Cockroach for CockroachDialect.

For third-party dialects, the expected value is the fully-qualified class name, for example com.acme.hibernate.AcmeDbDialect.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT

Show more

string

selected automatically for most popular databases

quarkus.hibernate-orm."persistence-unit-name".dialect.mariadb.bytes-per-character

Specifies the bytes per character to use based on the database’s configured charset.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MARIADB_BYTES_PER_CHARACTER

Show more

int

4

quarkus.hibernate-orm."persistence-unit-name".dialect.mariadb.no-backslash-escapes

Specifies whether the NO_BACKSLASH_ESCAPES sql mode is enabled.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MARIADB_NO_BACKSLASH_ESCAPES

Show more

boolean

false

quarkus.hibernate-orm."persistence-unit-name".dialect.mariadb.storage-engine

The storage engine to use.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MARIADB_STORAGE_ENGINE

Show more

string

quarkus.hibernate-orm."persistence-unit-name".dialect.mysql.bytes-per-character

Specifies the bytes per character to use based on the database’s configured charset.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MYSQL_BYTES_PER_CHARACTER

Show more

int

4

quarkus.hibernate-orm."persistence-unit-name".dialect.mysql.no-backslash-escapes

Specifies whether the NO_BACKSLASH_ESCAPES sql mode is enabled.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MYSQL_NO_BACKSLASH_ESCAPES

Show more

boolean

false

quarkus.hibernate-orm."persistence-unit-name".dialect.mysql.storage-engine

The storage engine to use.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MYSQL_STORAGE_ENGINE

Show more

string

quarkus.hibernate-orm."persistence-unit-name".dialect.oracle.extended

Support for Oracle’s MAX_STRING_SIZE = EXTENDED.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_ORACLE_EXTENDED

Show more

boolean

false

quarkus.hibernate-orm."persistence-unit-name".dialect.oracle.autonomous

Specifies whether this database is running on an Autonomous Database Cloud Service.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_ORACLE_AUTONOMOUS

Show more

boolean

false

quarkus.hibernate-orm."persistence-unit-name".dialect.oracle.application-continuity

Specifies whether this database is accessed using a database service protected by Application Continuity.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_ORACLE_APPLICATION_CONTINUITY

Show more

boolean

false

quarkus.hibernate-orm."persistence-unit-name".dialect.mssql.compatibility-level

The compatibility_level as defined in sys.databases.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MSSQL_COMPATIBILITY_LEVEL

Show more

string

Query related configuration

デフォルト

quarkus.hibernate-orm."persistence-unit-name".query.query-plan-cache-max-size

The maximum size of the query plan cache. see #org.hibernate.cfg.AvailableSettings#QUERY_PLAN_CACHE_MAX_SIZE

Environment variable: QUARKUS_HIBERNATE_ORM_QUERY_QUERY_PLAN_CACHE_MAX_SIZE

Show more

int

2048

quarkus.hibernate-orm."persistence-unit-name".query.default-null-ordering

Default precedence of null values in ORDER BY clauses.

Valid values are: none, first, last.

Environment variable: QUARKUS_HIBERNATE_ORM_QUERY_DEFAULT_NULL_ORDERING

Show more

noneNull precedence not specified., firstNull values occur at the beginning of the ORDER BY clause., lastNull values occur at the end of the ORDER BY clause.

noneNull precedence not specified.

quarkus.hibernate-orm."persistence-unit-name".query.in-clause-parameter-padding

Enables IN clause parameter padding which improves statement caching.

Environment variable: QUARKUS_HIBERNATE_ORM_QUERY_IN_CLAUSE_PARAMETER_PADDING

Show more

boolean

true

quarkus.hibernate-orm."persistence-unit-name".query.fail-on-pagination-over-collection-fetch

When limits cannot be applied on the database side, trigger an exception instead of attempting badly-performing in-memory result set limits.

When pagination is used in combination with a fetch join applied to a collection or many-valued association, the limit must be applied in-memory instead of on the database. This should be avoided as it typically has terrible performance characteristics.

Environment variable: QUARKUS_HIBERNATE_ORM_QUERY_FAIL_ON_PAGINATION_OVER_COLLECTION_FETCH

Show more

boolean

false

JDBC related configuration

デフォルト

quarkus.hibernate-orm."persistence-unit-name".jdbc.timezone

The time zone pushed to the JDBC driver. See quarkus.hibernate-orm.mapping.timezone.default-storage.

Environment variable: QUARKUS_HIBERNATE_ORM_JDBC_TIMEZONE

Show more

string

quarkus.hibernate-orm."persistence-unit-name".jdbc.statement-fetch-size

How many rows are fetched at a time by the JDBC driver.

Environment variable: QUARKUS_HIBERNATE_ORM_JDBC_STATEMENT_FETCH_SIZE

Show more

int

quarkus.hibernate-orm."persistence-unit-name".jdbc.statement-batch-size

The number of updates (inserts, updates and deletes) that are sent by the JDBC driver at one time for execution.

Environment variable: QUARKUS_HIBERNATE_ORM_JDBC_STATEMENT_BATCH_SIZE

Show more

int

Fetching logic configuration

デフォルト

quarkus.hibernate-orm."persistence-unit-name".fetch.batch-size

The size of the batches used when loading entities and collections.

-1 means batch loading is disabled.

Environment variable: QUARKUS_HIBERNATE_ORM_FETCH_BATCH_SIZE

Show more

int

16

quarkus.hibernate-orm."persistence-unit-name".fetch.max-depth

The maximum depth of outer join fetch tree for single-ended associations (one-to-one, many-to-one).

A 0 disables default outer join fetching.

Environment variable: QUARKUS_HIBERNATE_ORM_FETCH_MAX_DEPTH

Show more

int

Caching configuration

デフォルト

quarkus.hibernate-orm."persistence-unit-name".cache."cache".expiration.max-idle

The maximum time before an object of the cache is considered expired.

Environment variable: QUARKUS_HIBERNATE_ORM_CACHE__CACHE__EXPIRATION_MAX_IDLE

Show more

Duration 

100s

quarkus.hibernate-orm."persistence-unit-name".cache."cache".memory.object-count

The maximum number of objects kept in memory in the cache.

Environment variable: QUARKUS_HIBERNATE_ORM_CACHE__CACHE__MEMORY_OBJECT_COUNT

Show more

10000

Discriminator related configuration

デフォルト

quarkus.hibernate-orm."persistence-unit-name".discriminator.ignore-explicit-for-joined

Existing applications rely (implicitly or explicitly) on Hibernate ignoring any DiscriminatorColumn declarations on joined inheritance hierarchies. This setting allows these applications to maintain the legacy behavior of DiscriminatorColumn annotations being ignored when paired with joined inheritance.

Environment variable: QUARKUS_HIBERNATE_ORM_DISCRIMINATOR_IGNORE_EXPLICIT_FOR_JOINED

Show more

boolean

false

Logging configuration

デフォルト

Logs SQL bind parameters.

Setting it to true is obviously not recommended in production.

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_BIND_PARAMETERS

Show more

boolean

false

quarkus.hibernate-orm."persistence-unit-name".log.sql

Show SQL logs and format them nicely.

Setting it to true is obviously not recommended in production.

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_SQL

Show more

boolean

false

quarkus.hibernate-orm."persistence-unit-name".log.format-sql

Format the SQL logs if SQL log is enabled

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_FORMAT_SQL

Show more

boolean

true

quarkus.hibernate-orm."persistence-unit-name".log.highlight-sql

Highlight the SQL logs if SQL log is enabled

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_HIGHLIGHT_SQL

Show more

boolean

true

quarkus.hibernate-orm."persistence-unit-name".log.jdbc-warnings

Whether JDBC warnings should be collected and logged.

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_JDBC_WARNINGS

Show more

boolean

depends on dialect

quarkus.hibernate-orm."persistence-unit-name".log.queries-slower-than-ms

If set, Hibernate will log queries that took more than specified number of milliseconds to execute.

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_QUERIES_SLOWER_THAN_MS

Show more

Schema management configuration

デフォルト

quarkus.hibernate-orm."persistence-unit-name".schema-management.strategy

Select whether the database schema is generated or not.

drop-and-create is awesome in development mode.

This defaults to 'none'.

However if Dev Services is in use and no other extensions that manage the schema are present the value will be automatically overridden to 'drop-and-create'.

Accepted values: none, create, drop-and-create, drop, update, validate.

Environment variable: QUARKUS_HIBERNATE_ORM_SCHEMA_MANAGEMENT_STRATEGY

Show more

noneNo schema action., createCreate the schema., drop-and-createDrop and then recreate the schema., dropDrop the schema., updateUpdate (alter) the database schema., validateValidate the database schema.

noneNo schema action.

quarkus.hibernate-orm."persistence-unit-name".schema-management.create-schemas

If Hibernate ORM should create the schemas automatically (for databases supporting them).

Environment variable: QUARKUS_HIBERNATE_ORM_SCHEMA_MANAGEMENT_CREATE_SCHEMAS

Show more

boolean

false

quarkus.hibernate-orm."persistence-unit-name".schema-management.halt-on-error

Whether we should stop on the first error when applying the schema.

Environment variable: QUARKUS_HIBERNATE_ORM_SCHEMA_MANAGEMENT_HALT_ON_ERROR

Show more

boolean

false

quarkus.hibernate-orm."persistence-unit-name".schema-management.extra-physical-table-types

Additional database object types to include in schema management operations.

By default, Hibernate ORM only considers tables and sequences when performing schema management operations. This setting allows you to specify additional database object types that should be included, such as "MATERIALIZED VIEW", "VIEW", or other database-specific object types.

The exact supported values depend on the underlying database and dialect.

Environment variable: QUARKUS_HIBERNATE_ORM_SCHEMA_MANAGEMENT_EXTRA_PHYSICAL_TABLE_TYPES

Show more

string

Database scripts related configuration

デフォルト

quarkus.hibernate-orm."persistence-unit-name".scripts.generation

Select whether the database schema DDL files are generated or not. Accepted values: none, create, drop-and-create, drop, update, validate.

Environment variable: QUARKUS_HIBERNATE_ORM_SCRIPTS_GENERATION

Show more

noneNo schema action., createCreate the schema., drop-and-createDrop and then recreate the schema., dropDrop the schema., updateUpdate (alter) the database schema., validateValidate the database schema.

noneNo schema action.

quarkus.hibernate-orm."persistence-unit-name".scripts.generation.create-target

Filename or URL where the database create DDL file should be generated.

Environment variable: QUARKUS_HIBERNATE_ORM_SCRIPTS_GENERATION_CREATE_TARGET

Show more

string

quarkus.hibernate-orm."persistence-unit-name".scripts.generation.drop-target

Filename or URL where the database drop DDL file should be generated.

Environment variable: QUARKUS_HIBERNATE_ORM_SCRIPTS_GENERATION_DROP_TARGET

Show more

string

Flush configuration

デフォルト

quarkus.hibernate-orm."persistence-unit-name".flush.mode

The default flushing strategy, or when to flush entities to the database in a Hibernate session: before every query, on commit, …​

This default can be overridden on a per-session basis with Session#setHibernateFlushMode() or on a per-query basis with the hint HibernateHints#HINT_FLUSH_MODE.

See the javadoc of org.hibernate.FlushMode for details.

Environment variable: QUARKUS_HIBERNATE_ORM_FLUSH_MODE

Show more

manualThe org.hibernate.Session is only flushed when org.hibernate.Session#flush() is called explicitly. This mode is very efficient for read-only transactions., commitThe org.hibernate.Session is flushed when org.hibernate.Transaction#commit() is called. It is never automatically flushed before query execution., autoThe org.hibernate.Session is flushed when org.hibernate.Transaction#commit() is called, and is sometimes flushed before query execution in order to ensure that queries never return stale state. This is the default flush mode., alwaysThe org.hibernate.Session is flushed when org.hibernate.Transaction#commit() is called and before every query. This is usually unnecessary and inefficient.

autoThe org.hibernate.Session is flushed when org.hibernate.Transaction#commit() is called, and is sometimes flushed before query execution in order to ensure that queries never return stale state. This is the default flush mode.

期間フォーマットについて

期間の値を書くには、標準の java.time.Duration フォーマットを使います。 詳細は Duration#parse() Java API documentation を参照してください。

数字で始まる簡略化した書式を使うこともできます:

  • 数値のみの場合は、秒単位の時間を表します。

  • 数値の後に ms が続く場合は、ミリ秒単位の時間を表します。

その他の場合は、簡略化されたフォーマットが解析のために java.time.Duration フォーマットに変換されます:

  • 数値の後に hms が続く場合は、その前に PT が付けられます。

  • 数値の後に d が続く場合は、その前に P が付けられます。

関連コンテンツ