문제

방금 약간 비효율적으로 보이는 다른 사람이 쓴 기능을 뛰어 넘었지만 JPA에 대한 제 지식은 동면하지 않은 휴대용 솔루션을 찾는 것이 좋지 않습니다.

간단히 말해서, 루프 내에서 호출 된 DAO 메소드는 각각의 새로운 엔티티를 삽입하기 위해 "EntityManager.Merge (Object);"를 수행합니다.

JPA 사양에 엔터티 목록을 DAO 메소드로 전달하고 모든 단일 객체에 대해 병합을 호출하는 대신 벌크 / 배치 삽입물을 수행하는 방법이 없습니까?

또한 DAO 메소드가 "@Transactional"으로 주석이 달리기 때문에 모든 단일 병합 통화가 자체 거래 내에서 발생하는지 궁금합니다. 이는 성능에 도움이되지 않습니다.

아이디어가 있습니까?

도움이 되었습니까?

해결책

바닐라 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 스프링 주석입니다. 보다 거래 관리 스프링 참조에서.

다른 팁

당신이 할 수있는 일, 당신이 교활한 분위기에 있다면 :

@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을보고 벤치 마크를하는 것은 흥미로울 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top