質問
私は少し非効率です他の人によって書かれた機能に飛び込んだが、JPAの私の知識は、特定の休止状態ではないのポータブル解決策を見つけるために良いことではありません。
簡単に言えば、新しいエンティティのそれぞれを挿入するために、ループ内で呼び出されるダオ方法がない「entityManager.merge(オブジェクト);」。
イマイチ」はダオ方法にエンティティのリストを渡して、代わりに一つ一つのオブジェクトに対してマージ呼び出すのバルク/バッチ挿入を行うにはJPA仕様で定義されている方法はありますか?
プラスので、ダオの方法は、すべての単一のマージ・コールは、独自のトランザクション内で起こっている場合、私は思ったんだけど、「@Transactional」...パフォーマンスを助けないであろう/ wの注釈が付けられてます。
任意のアイデア?
解決
ノーバニラJPAにはバッチ挿入操作はありません。
はい、各インサートは、独自のトランザクション内で実行されます。 @Transactional
属性は、(修飾子なしで)REQUIRED
の伝搬レベルを(それが存在しない場合、トランザクションを作成します)を意味します。あなたが持っていると仮定します:
public class Dao {
@Transactional
public void insert(SomeEntity entity) {
...
}
}
あなたはこれを行います
public class Batch {
private Dao dao;
@Transactional
public void insert(List<SomeEntity> entities) {
for (SomeEntity entity : entities) {
dao.insert(entity);
}
}
public void setDao(Dao dao) {
this.dao = dao;
}
}
インサートのグループ全体が単一のトランザクションでラップされますこの方法。あなたがインサートの非常に多くの話をしている場合は10000、1000年のグループに分割することができますまたは何でも十分に大きいコミットされていないトランザクションとして動作すると、リソースのデータベースを餓死し、おそらくサイズのみに失敗することがあります。
注: @Transactional
は春の注釈です。 トランザクション管理は、春のリファレンスからを参照してください。
他のヒント
あなたは何ができるか、あなたは狡猾な気分にあった場合は、次のとおりです。
@Entity
public class SomeEntityBatch {
@Id
@GeneratedValue
private int batchID;
@OneToMany(cascade = {PERSIST, MERGE})
private List<SomeEntity> entities;
public SomeEntityBatch(List<SomeEntity> entities) {
this.entities = entities;
}
}
List<SomeEntity> entitiesToPersist;
em.persist(new SomeEntityBatch(entitiesToPersist));
// remove the SomeEntityBatch object later
ので、エンティティは、単一の操作で挿入されるようになりますカスケード、のます。
私は単純にループ内の個々のオブジェクトを永続化する上でこれを行うに任意の実用的な利点がある疑い。これは、ベンチマークに、JPA実装が放出されることにSQLを見て興味深いものになるだろう。