흰 스타렉스에서 내가 내리지

[JPA] 배치 처리 본문

JPA

[JPA] 배치 처리

주씨. 2024. 4. 28. 04:41
728x90

# 배치 처리

  • 수백만 건의 데이터를 배치 처리해야 하는 상황
  • 일반적인 방식으로 엔티티를 계속 조회하면 영속성 컨텍스트에 아주 많은 엔티티가 쌓이면서 메모리 부족 오류가 발생한다.
  • 따라서 이런 배치 처리는 적절한 단위로 영속성 컨텍스트를 초기화해야 한다. 

 

# JPA 등록 배치

  • 수만 건 이상의 엔티티를 한 번에 등록할 떄 주의할 점은 영속성 컨텍스트에 엔티티가 계속 쌓이지 않도록 일정 단위마다 영속성 컨텍스트의 엔티티를 데이터베이스에 플러시하고 영속성 컨텍스트를 초기화해야 한다.
  • 만약 이렇게 안하면, 영속성 컨텍스트에 너무 많은 엔티티가 저장되면서 메모리 부족 오류가 발생할 수 있다.
public void batch(){
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    
    for (int i = 0; i < 100000; i++){
        Member member = new Member("member" + i);
        em.persist(member);
        
        // 100건마다 플러시와 영속성 컨텍스트 초기화
        if ( i % 100 == 0 ){
            em.flush();
            em.clear();
        }
    }
    
    tx.commit();
    em.close();

}

 

  • 위 코드는 엔티티를 100건 저장할 때마다 플러시를 호출하고 영속성 컨텍스트를 초기화한다.

 

# 수정 배치 처리

  • 배치 처리는 아주 많은 데이터를 조회해서 수정한다.
  • 수많은 데이터를 한 번에 메모리에 올려둘 수 없기 때문에 2가지 방법을 주로 사용한다.
    • 1. 페이징 처리 : 데이터베이스 페이징 기능을 사용한다.
    • 2. 커서 : 데이터베이스가 지원하는 커서 기능을 사용한다.

 

public void jpaPagingBatch(){
    EntityTransaction tx = em.getTransaction();
    tx.begin();

    int pageSize = 100;
    for (int i = 0; i < 10; i++){
        List<Member> resultList = em.createQuery("select m from Member m", Member.class)
                .setFirstResult(i * pageSize)
                .setMaxResults(pageSize)
                .getResultList();
        
        // 비즈니스 로직 실행
        for (Member member : resultList) {
            member.setAge(member.getAge() - 1);
        }
        
        em.flush();
        em.clear();

    }
    
    tx.commit();
    em.close();
}

 

  • 위 코드는 한 번에 100건씩 페이징 쿼리로 조회하면서 회원의 나이를 1 감소시킨다.
  • 그리고 페이지 단위마다 영속성 컨텍스트를 플러시하고 초기화한다.