JPAとHibernateのパフォーマンスの問題を自動的に検出できるツールがあると想像してください。 超自然オプティマイザは、そのツールです!
はじめに
なぜ、いつJpaまたはHibernateを使用する必要があるのか疑問に思っているなら、この記事ではこの非常に一般的な質問への答えを提供します。 この質問は/r/java Redditチャンネルで非常に頻繁に尋ねられたので、JPAとHibernateの長所と短所についての詳細な答えを書く価値があると判断しました。
JPAは2006年に最初にリリースされて以来、標準でしたが、Javaを使用してデータアクセスレイヤーを実装できる唯一の方法ではありません。 JPAまたはその他の一般的な代替手段を使用することの利点と欠点について説明します。
なぜ、いつJDBCが作成されたのか
1997年、Java1。これは、アプリケーションコードを変更することなく、一連のインターフェイスを使用して一度データアクセスレイヤーを記述し、JDBC APIを実装するリレーショナルデー
JDBC APIには、トランザクション境界を制御し、Statement
APIを介して単純なSQL文を作成するためのConnection
インタフェース、またはPreparedStatement
APIを介してパラメータ値をバインドしたがって、post
データベーステーブルがあり、100行を挿入すると仮定すると、JDBCでこの目標を達成する方法は次のとおりです:
int postCount = 100;int batchSize = 50;try (PreparedStatement postStatement = connection.prepareStatement(""" INSERT INTO post ( id, title ) VALUES ( ?, ? ) """)) { for (int i = 1; i <= postCount; i++) { if (i % batchSize == 0) { postStatement.executeBatch(); } int index = 0; postStatement.setLong( ++index, i ); postStatement.setString( ++index, String.format( "High-Performance Java Persistence, review no. %1$d", i ) ); postStatement.addBatch(); } postStatement.executeBatch();} catch (SQLException e) { fail(e.getMessage());}
複数行のテキストブロックとtry-with-resourcesブロックを利用してPreparedStatement
close
呼び出しを排除しましたが、実装はまだ非常に冗長です。 バインドパラメータは1
から始まり、0
ではなく、他のよく知られたApiから慣れ親しんでいることに注意してください。
最初の10行をフェッチするには、PreparedStatement
を介してSQLクエリを実行する必要があります。ResultSet
テーブルベースのクエリ結果を表します。 ただし、アプリケーションはJSONやDtoなどの階層構造を使用して親子の関連付けを表すため、ほとんどのアプリケーションでは、次の例に示すように、JDBCResultSet
を:
int maxResults = 10;List<Post> posts = new ArrayList<>();try (PreparedStatement preparedStatement = connection.prepareStatement(""" SELECT p.id AS id, p.title AS title FROM post p ORDER BY p.id LIMIT ? """)) { preparedStatement.setInt(1, maxResults); try (ResultSet resultSet = preparedStatement.executeQuery()) { while (resultSet.next()) { int index = 0; posts.add( new Post() .setId(resultSet.getLong(++index)) .setTitle(resultSet.getString(++index)) ); } }} catch (SQLException e) { fail(e.getMessage());}
ここでも、テキストブロック、try-with-resources、およびFluentスタイルのAPIを使用してPost
オブジェクトを構築しているため、これはJDBCでこれを書くことができる最も良それにもかかわらず、JDBC APIは依然として非常に冗長であり、さらに重要なことに、最新のデータアクセスレイヤーを実装するときに必要な多くの機能が欠け:
- クエリ結果セットからオブジェクトを直接取得する方法。 上記の例で見たように、
ReusltSet
を反復処理し、列の値を抽出してPost
オブジェクトプロパティを設定する必要があります。 - デフォルトの非バッチモードからバッチ処理を使用するモードに切り替えるときに、データアクセスコードを書き換えることなく、ステートメントをバッ
- オプティミスティックロックのサポート
- 基礎となるデータベース固有のTop-NおよびNext-Nクエリ構文を隠すページネーションAPI
Hibernateが作成された理由と時期
1999年、SunはJ2EE(Java Enterprise Edition)をリリースし、Entity Beanと呼ばれるJDBCの代替を提供した。
しかし、エンティティBeanは遅く、複雑すぎ、使用が面倒であることが悪名高いため、2001年にGavin KingはデータベーステーブルをPojo(Plain Old Java Objects)にマップできるORMフレームワーク
エンティティBeanよりも軽量でJDBCよりも冗長であるため、Hibernateはますます人気を博し、すぐにJDO、iBatis、Oracle TopLink、Apache Cayenneに勝って最も人気のあるJava永続性フレームワーク
なぜ、いつJPAが作成されたのですか?
Hibernateプロジェクトの成功から学び、Java EEプラットフォームはHibernateとOracle TopLinkの方法を標準化することに決めました。
JPAは単なる仕様であり、独自に使用することはできず、Hibernate、EclipseLink、OpenJPAなどのJPAプロバイダによって実装される標準永続性APIを定義するインターフェイスのセッ
JPAを使用する場合は、データベース表とそれに関連するJava entityオブジェクトとの間のマッピングを定義する必要があります:
@Entity@Table(name = "post")public class Post { @Id private Long id; private String title; public Long getId() { return id; } public Post setId(Long id) { this.id = id; return this; } public String getTitle() { return title; } public Post setTitle(String title) { this.title = title; return this; }}
その後、100個のpost
レコードを保存した前の例を次のように書き換えることができます:
for (long i = 1; i <= postCount; i++) { entityManager.persist( new Post() .setId(i) .setTitle( String.format( "High-Performance Java Persistence, review no. %1$d", i ) ) );}
JDBCバッチ挿入を有効にするには、単一の構成プロパティを提供するだけです:
<property name="hibernate.jdbc.batch_size" value="50"/>
このプロパティが提供されると、Hibernateはデータアクセスコードの変更を必要とせずに、非バッチからバッチに自動的に切り替えることができます。
そして、最初の10行のpost
行をフェッチするために、次のJPQLクエリを実行できます:
int maxResults = 10;List<Post> posts = entityManager.createQuery(""" select p from post p order by p.id """, Post.class).setMaxResults(maxResults).getResultList();
これをJDBCバージョンと比較すると、JPAの方がはるかに使いやすいことがわかります。
JPAとHibernate
JPAを使用することの利点と欠点は、一般的に、特にHibernateには多くの利点があります。
- エンティティまたはDtoを取得できます。 階層的な親子DTO投影法を取得することもできます。
- データ-アクセス-コードを変更せずにJDBCバッチ処理を有効にすることができます。
- 楽観的ロックをサポートしています。
- 基になるデータベース固有の構文とは独立した悲観的なロック抽象化を持っているので、読み取りと書き込みロック、またはスキップロックを取得
- データベースに依存しないページネーションAPIがあります。
- この記事で説明しているように、IN query句に値の
List
を指定できます。 - プライマリノードをオフロードできる強く一貫性のあるキャッシュソリューションを使用することができます。
- Hibernate Enversを介した監査ロギングのサポートが組み込まれています。
- マルチテナンシーのサポートが組み込まれています。
- Hibernate hbm2ddlツールを使用してエンティティマッピングから初期スキーマスクリプトを生成することができます。
- ネイティブSQLクエリを自由に実行できるだけでなく、SqlResultSetMappingを使用してJDBC
ResultSet
をJPAエンティティまたはDtoに変換できます。
JPAとHibernateを使用することの欠点は次のとおりです:
- JPAの入門は非常に簡単ですが、専門家になるには、そのマニュアルを読むだけでなく、データベースシステムの仕組み、SQL標準、プロジェクト関係データベースで使
- フラッシュ操作の順序のように、初心者を驚かせるかもしれないいくつかの直感的ではない動作があります。
- Criteria APIはかなり冗長であるため、Codotaのようなツールを使用して動的クエリをより簡単に記述する必要があります。
コミュニティ全体と人気のある統合
JPAとHibernateは非常に人気があります。 Snykによる2018年のJava ecosystem reportによると、リレーショナルデータベースと対話するすべてのJava開発者の54%がHibernateを使用しています。
この結果はGoogle Trendsに裏打ちされている可能性があります。 たとえば、JpaのGoogleの傾向を主要な競合他社(MyBatis、QueryDSL、jOOQなど)と比較すると、JPAは何倍も人気があり、支配的な市場シェアの地位を失う兆候はないことがわかりま
を使用する理由と時期は、非常に人気があることは、次のような多くの利点をもたらします:
- Spring Data JPA統合は魅力のように機能します。 実際、JpaとHibernateが非常に人気がある最大の理由の1つは、Spring BootがSpring Data JPAを使用しているためです。
- 何か問題がある場合は、これらの30kのHibernate関連のStackOverflow回答と16kのJPA関連のStackOverflow回答が解決策を提供する可能性があります。
- 利用可能な73k Hibernateチュートリアルがあります。 私のサイトだけで、JPAとHibernateを最大限に活用する方法を教える250以上のJPAとHibernateのチュートリアルを提供しています。
- 私のHigh-Performance Java Persistence video courseのように、あなたも使用できる多くのビデオコースがあります。
- AmazonにはHibernateに関する300以上の本がありますが、そのうちの一つは私の高性能Java永続性の本です。
JPA alternatives
Javaエコシステムについての最大のものの一つは、高品質のフレームワークの豊富さです。 JPAとHibernateがユースケースに適していない場合は、次のフレームワークのいずれかを使用できます:
- MyBatisは、非常に軽量なSQLクエリマッパーフレームワークです。これにより、SQL、JPA、Lucene、およびMongoDBクエリを動的に構築できます。
- jOOQは、基になるテーブル、ストアドプロシージャ、および関数のJavaメタモデルを提供し、非常に直感的なDSLを使用して、タイプセーフな方法でSQLクエリを動的
だから、あなたのために最適なものを使用してください。
オンラインワークショップ
あなたがこの記事を楽しんでいれば、私はあなたが私の今後の4-day x4hours High-Performance Java Persistence Online Workshopを愛するつもりです
結論
この記事では、JPAが作成された理由と、いつ使用する必要があるかを見ました。 JPAには多くの利点がありますが、JPAとHibernateが現在のアプリケーション要件に最適でない場合は、他にも多くの高品質の代替手段があります。
そして、時には、私のHigh-Performance Java Persistence bookのこの無料サンプルで説明したように、JPAまたは他のフレームワークのどちらかを選択する必要さえありません。 JPAとjOOQのようなフレームワークを簡単に組み合わせることで、両方の長所を最大限に活用できます。