JPA EntityManagerを使用してバッチ挿入を使用できる方法はありますか。私はこれを達成する直接的な方法はないことを知っていますが、このメカニズムを達成する何らかの方法がなければなりません。
実際には、挿入操作ごとに300ミリ秒かかります。これは、単一挿入ではなくバッチ挿入を使用して削減したいものです。
現在、単一の挿入に対して実行しているコードを使用します
@PersistenceContext(unitName = "testing")
EntityManager eM;
Query querys = this.eM.createNativeQuery(insertQuery);
for (String s : someList) {
//setting parameters
querys.executeUpdate();
}
前もって感謝します。
JPAを使用してバッチ書き込みを実行することはisですが、永続性プロバイダー、データベース、およびJDBCドライバーの特定の実装に大きく依存します。たとえば、この 記事 は、EclipseLink JPA 2.3とOracleデータベースを使用してバッチ書き込み(最適化#8)を有効にする方法を説明しています。特定の環境で同様の構成パラメーターを探します。
トランザクションがループを囲むかどうかに応じて、通常、バッチ処理はすでにケースで発生しています。
JPAは、すべての更新をL1キャッシュに収集し、通常、トランザクションがコミットされると、そのすべてをバッチでDBに書き込みます。これは、JDBCでのバッチ処理と実際にはそれほど違いはありません。JDBCでは、更新メソッドを呼び出すまで、追加するすべてのバッチ項目も一時的にメモリ内にあります。
潜在的な問題は、JPAが実際にこのバッチ処理をまったく行わないこと、およびトランザクションのコミット時またはしきい値に達した場合にバッチ処理を行うことを強く保証していないことですが、実際にはほとんどすべての場合、特にそのような場合に関連する場合単純な更新ループ、実際にバッチ処理を行います。
1つの問題は、JPAが実際に既にバッチ処理を行っている場合でも、バッチサイズを制御する必要がある場合があることです。他の回答によってリンクされている記事は、そのための非常に有用な情報を提供します。
最後に、L1キャッシュがループで成長し続けることに注意する必要があります。したがって、更新の数が非常に多い場合は、定期的にクリアしてください。または、ビジネスロジックがそれを維持できる場合は、複数のトランザクションで部分的な更新を行います。例えば。トランザクション1のアイテム0から100.000、トランザクション2の100.001から200.000など.
これはかなり古い質問であり、回答は受け入れられています。それにもかかわらず、私はこの非常に具体的な主題「JPAバッチ挿入」に新しい答えをしたいと思います。
@PersistenceContext
private EntityManager entityManager;
@Value("${hibernate.jdbc.batch_size}")
private int batchSize;
public <T extends MyClass> Collection<T> bulkSave(Collection<T> entities) {
final List<T> savedEntities = new ArrayList<T>(entities.size());
int i = 0;
for (T t : entities) {
savedEntities.add(persistOrMerge(t));
i++;
if (i % batchSize == 0) {
// Flush a batch of inserts and release memory.
entityManager.flush();
entityManager.clear();
}
}
return savedEntities;
}
private <T extends MyClass> T persistOrMerge(T t) {
if (t.getId() == null) {
entityManager.persist(t);
return t;
} else {
return entityManager.merge(t);
}
}
ソース: http://frightanic.com/software-development/jpa-batch-inserts/
JPA自体には、バッチ処理の設定がありません。ただし、実装に依存する設定がいくつかあります。 これは休止状態の例です 。