4

他の誰かが書いた機能に飛びつきましたが、少し非効率に見えますが、JPAに関する私の知識は、Hibernate固有ではないポータブルソリューションを見つけるのにそれほど適していません。

一言で言えば、新しいエンティティのそれぞれを挿入するためにループ内で呼び出されるDaoメソッドは、「entityManager.merge(object);」を実行します。

JPA仕様で定義されている方法で、エンティティのリストをDaoメソッドに渡し、すべてのオブジェクトに対してマージを呼び出す代わりに、一括/バッチ挿入を実行する方法はありませんか?

さらに、Daoメソッドには「@Transactional」という注釈が付けられているため、すべてのマージ呼び出しが独自のトランザクション内で発生しているのではないかと思います...これはパフォーマンスに役立ちません。

何か案が?

4

2 に答える 2

7

いいえ、バニラ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;
  }
}

このようにして、挿入のグループ全体が単一のトランザクションにラップされます。非常に多くの挿入について話している場合は、1000、10000のグループに分割するか、十分に大きなコミットされていないトランザクションとして機能するものは、リソースのデータベースを枯渇させ、サイズだけで失敗する可能性があります。

注: @TransactionalはSpringアノテーションです。SpringReferenceのTransactionalManagementを参照してください。

于 2009-09-01T15:15:39.380 に答える
0

あなたが狡猾な気分だった場合、あなたができることは次のとおりです。

@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

カスケードのため、エンティティが1回の操作で挿入されます。

ループ内の個々のオブジェクトを単純に永続化するよりも、これを行うことに実際的な利点があるとは思えません。JPA実装が発行したSQLを調べて、ベンチマークを行うのは興味深いことです。

于 2012-06-26T17:14:05.717 に答える