セッションレスアーキテクチャ
JPAは、エンティティBeanを永続化するためには、エンティティBeanをPersistenceContextにアタッチする必要があるように設計されています。
つまり、JPAはアタッチ/デタッチセマンティクスを要求します。これには、次のような多くの結果があります。
- 開発者は、選択したオブジェクトを簡単に制御して永続化することができません。
- アタッチされたすべてのBeanは、フラッシュするために有効な状態である必要があります。
- フラッシュは暗黙的にすべてのダーティ状態をフラッシュします(そのため、どこででも作成されたダーティ状態は暗黙的にフラッシュされます)。
- フラッシュは、予期しない方法でステートメントの順序を変更することがあります(デッドロックを引き起こす可能性があります)。
- EntityManagerのスコープは、トランザクションのスコープと共に管理する必要があります。
Ebeanアーキテクチャ
- エンティティマネージャはありません。トランザクションのみを管理します。
- 各エンティティBeanのダーティ状態
- 永続化(保存、削除)にはPersistenceContextは必要ありません。
- PersistenceContextはトランザクションにアタッチされます。
- 部分的に設定されたBeanは常に想定されます。
永続化機能
JDBCバッチ制御
JPAでは
- JDBCバッチサイズの制御がありません。
- 大規模な挿入を最適化するためにgetGeneratedKeysをオフにする機能がありません。
- カスケード動作をオフにする機能がありません(完全な制御を行うため)。
JDBCバッチを使用することは、Ebeanが永続化時に最適なパフォーマンスを得るために重要です。Ebeanでは、トランザクションにJDBCバッチバッファがアタッチされており、JDBCバッチを使用して永続化呼び出しをシームレスにバッチ処理できます。
Ebeanは、バッチサイズ、getGeneratedKeys、カスケード動作を含む、トランザクションを介してJDBCバッチを完全に制御できます。JPAとは異なり、Ebeanではバッチ処理を完全に制御して最適化するのは簡単です。
トランザクション
JDBCバッチの完全な制御に加えて、Ebeanはトランザクションで次の機能を提供します。
- トランザクションコールバックの登録(コミット後コールバックなど)
- ユーザー定義オブジェクトの設定と取得
- トランザクションに対してL2キャッシュをスキップするかどうかを指定します。
Raw JDBC
Ebeanは、必要な場合にjava.sql.Connectionへのアクセスを提供し、L2キャッシュの無効化のために変更されたテーブルをEbeanに通知するtransaction.addModification(table, ...)メソッドも提供します。
Ebeanには、SQLバルクステートメントとストアドプロシージャの呼び出しを容易にするSqlUpdateとCallableSqlも組み込まれています。
トランザクション分離レベル
Ebeanでは、より高い分離レベルでトランザクションを開始できます。JPAはこの機能をサポートしていません。
ステートレス更新
Ebeanを使用すると、オブジェクトをロードせずにBean(またはオブジェクトグラフ)を設定してupdate()できます。これは、JSONからエンティティオブジェクトグラフを設定して更新を実行する必要があるRESTのようなAPIで役立ちます。
クエリ機能
findCount
Ebeanには、クエリのコピーを作成してカウントの実行を最適化する(フェッチ、順序付けなどを削除する)組み込みのfindCountがあります。JPAではcount()関数を使用しますが、同じクエリをfindListタイプのクエリに使用することはできません。
findPagedList
JPAは、クエリに関する「合計カウント」と結果のページをサポートするPagedListクエリをサポートしていません。(Spring Data JPAは、このギャップをある程度埋めるのに役立ちます)。
findEach
JPAは、大規模なクエリを実行するためのサポートがありません。Ebeanには、永続化コンテキストの範囲、JDBCドライバのfetchSize、MySql固有の処理(MySqlには対処すべき固有の問題があるため)を考慮した大規模なクエリ(カーソル/ストリーミング)を実行するためのfindEachがあります。
findMap
JPAには、プロパティによってマップされたオブジェクトを返すEbeanのfindMapに相当するものはありません。
非同期クエリ
Ebeanは、findFutureList()、findFutureCount()、findFutureIds()を使用してFuturesを返すバックグラウンドでクエリを実行するための組み込みサポートを提供しています。これにより、キャンセルできるクエリを簡単に実行できます。
内部的に、findFutureCount()はPagedListクエリの一部として使用され、合計カウントクエリをfindList()クエリと並行して実行できます。
AS OFクエリ
JPAはまだSQL2011 AS OF クエリをサポートしていません。
VERSIONS BETWEENクエリ
JPAはまだSQL2011 VERSIONS BETWEEN クエリをサポートしていません。
ジェネリクス
JPAは初期APIでジェネリクスを使用できず、そのため理想的ではないQueryとTypedQueryの両方があります。
JPQL
JPQLは、部分オブジェクトのサポートが不十分であり、オブジェクトグラフのどの部分をフェッチするべきかを定義することで複雑なクエリをN + 1に対して最適化するためのサポートも不十分です。
現在の状態では、JPQLはORMクエリを最適化するための貧弱な言語です。JPA 2.1ではクエリヒントとしてfetch groupsのサポートが追加されましたが、これは使用がかなり不器用であり、サポートが比較的貧弱なクエリヒントにすぎず、最終的には混合ソース(L2、L3、DB)からのオブジェクトグラフの構築を制御するための重要な機能が不足しているという多くの問題があります。
JPAでは、アノテーションFetchType.EagerとFetchType.Lazyの強調とJPQLの制限により、ORMクエリを最適化するためのJPAの位置が悪くなっており、Ebeanがサポートするオブジェクトグラフの構築の制御レベルに到達できるかどうかは興味深いところです。
型安全なクエリ
JPA Criteriaクエリには少し「儀式」が多いと主張することもできますが、これによりクエリが冗長になり、読みづらくなります。
Ebean「クエリBean」
LocalDate today = new LocalDate();
List<Customer> customers =
new QCustomer()
.birthday.equalTo(today)
.createdAt.before(today.minusYears(2))
.findList();
JPA Criteria
LocalDate today = new LocalDate();
EntityManager em = ...;
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Customer> query = builder.createQuery(Customer.class);
Root<Customer> root = query.from(Customer.class);
Predicate hasBirthday = builder.equal(root.get(Customer_.birthday), today);
Predicate isLongTermCustomer = builder.lessThan(root.get(Customer_.createdAt), today.minusYears(2);
query.where(builder.and(hasBirthday, isLongTermCustomer));
List<Customer> customers = em.createQuery(query.select(root)).getResultList();
Javaアノテーション処理は、Ebean(「クエリBean」の生成に使用)とJPA(型安全なクエリの構築と実行を提供するためにJPAクエリメタモデルクラスの生成に使用)の両方で使用されます。
QueryDSL
多くのJPAユーザーは、標準のJPA CriteriaメタモデルオブジェクトよりもQueryDSLを使用することを好むと思います。
マッピング
コンストラクタ
JPAとは異なり、Ebeanはデフォルトコンストラクタを必要としません。
@View
Ebeanは、データベースビューに基づくエンティティを組み込みでサポートしています。
@Idのないエンティティ
Ebeanは、エンティティに@Idプロパティがあることを要求しません。これらのエンティティは「読み取り専用」と見なされ、永続化コンテキストを自動的にバイパスします。これらのエンティティは通常、レポート作成に使用されます。
命名規則
JPA仕様の命名規則には、混合ケースとアンダースコアの両方が含まれており、奇妙です。Ebeanのデフォルトの命名規則であるUnderscoreNamingConventionは、HibernateのImprovedNamingStrategyと一致し、JPA仕様の命名規則とは一致しません。
監査と@History
Ebeanは、@WhenCreated、@WhenModified、@WhoCreated、@WhoModified、および完全なSQL2011 @Historyサポートを組み込みでサポートしています。
DBのJSON
Ebeanには、Postgres JSONB、JSON、およびOracle、MySql(および近日中にSQL Server)の同様のタイプのマッピングサポートが含まれています。
DB ARRAY
Ebeanには、Postgres ARRAYタイプのマッピングサポートが含まれています。
@SoftDelete
Ebeanは、関連する永続的な削除、カスケード動作、およびクエリサポートを備えた@SoftDeleteをサポートしています。
@Draftable
Ebeanは、publish()関数とrestore()関数を備えた「ライブ」と「編集」機能を提供する@Draftableをサポートしています。