2009-09-01 2 views
3

약간 비효율적으로 보이는 필자가 작성한 기능으로 넘어 갔지만 JPA에 대한 지식은 최대 절전 모드가 아닌 휴대용 솔루션을 찾는 것이 좋지 않습니다.Portable JPA Batch/Bulk Insert

간단히 말해 Dao 메소드는 루프 내에서 새 엔티티 각각을 삽입하기 위해 호출되며 "entityManager.merge (object);"를 수행합니다.

JPA 스펙에서 엔티티 목록을 Dao 메소드에 전달하고 모든 단일 오브젝트에 대해 merge를 호출하는 대신 대량/배치 삽입을 수행하는 방법이 정의되어 있지 않습니까?

플러스 Dao 메서드가 "@Transactional"으로 주석 처리 되었기 때문에 모든 단일 병합 호출이 자체 트랜잭션 내에서 발생하는지 궁금합니다. 이는 성능에 도움이되지 않습니다.

아이디어가 있으십니까?

답변

6

아니요 바닐라 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 Reference에서 Transactional Management을 참조하십시오. 당신이 교활 기분이 있다면

+0

답장을 보내 주셔서 감사합니다. 내 Dao 메서드 내에서 병합() 대신 Persist() 사용하는 데 도움이 될 그들은 새로운 엔터티 때문에? – Lancelot

+0

merge()와 persist()에는 서로 다른 의미가 있습니다. 그것은 간단한 문제가 아니며 JPA에 대한 독서를 강력히 제안합니다. – cletus

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 

.

루프에서 개별 개체를 유지하는 것 이상의 작업을 수행하는 데 실질적인 이점이 있는지 의심 스럽습니다. JPA 구현이 방출 한 SQL을보고 벤치마킹하는 것이 흥미로울 것입니다.