관리 메뉴

한글창제의 기쁨

JPA Hibernate Bulk Save , Multi save 본문

Spring/Spring Data JPA

JPA Hibernate Bulk Save , Multi save

timesurfer 공간지배자 2019.01.03 18:09


일괄 처리


JDBC 일괄 처리

JDBC는 단일 PreparedStatement로 표현할 수있는 SQL 문을 함께 일괄 처리 할 수 ​​있도록 지원합니다. 구현 방식은 일반적으로 드라이버가 데이터베이스에 대한 네트워크 호출을 절약 할 수있는 한 번의 호출로 서버에 일괄 작업을 보냅니다. Hibernate는 JDBC 배치를 활용할 수 있습니다. 다음 설정은이 동작을 제어합니다.


hibernate.jdbc.batch_size

드라이버에게 배치를 실행하기 전에 Hibernate가 함께 배치 할 문장의 최대 수를 제어한다. 0 또는 음수는이 기능을 비활성화합니다.


hibernate.jdbc.batch_versioned_data

일부 JDBC 드라이버는 일괄 처리가 실행될 때 잘못된 행 수를 반환합니다. JDBC 드라이버가이 범주에 속하면이 설정을로 설정해야합니다 false. 그렇지 않으면 Hibernate가 여전히 버전 화 된 엔티티에 대해 DML을 배치하고 여전히 낙관적 인 잠금 검사에 반환 된 행 수를 사용하도록 허용하는 이것을 사용하는 것이 안전합니다. 5.0부터 기본값은 true입니다. 이전 버전 (3.x 및 4.x)은 이전에는 false였습니다.


hibernate.jdbc.batch.builder

일괄 처리 기능을 관리하는 데 사용되는 구현 클래스의 이름입니다. Hibernate의 기본 구현에서 전환하는 것은 거의 좋은 생각이 아니다. 그러나 원하는 경우이 설정은 org.hibernate.engine.jdbc.batch.spi.BatchBuilder사용할 구현을 명명합니다 .


hibernate.order_updates

Hibernate로 하여금 엔티티 타입과 업데이트되는 아이템의 프라이 머리 키 값에 의해 SQL 업데이트를 정렬하도록한다. 이렇게하면 더 많은 일괄 처리를 사용할 수 있습니다. 동시성이 높은 시스템에서는 트랜잭션 교착 상태가 줄어 듭니다. 성능에 영향을 미치기 때문에 이전과 후에 벤치마킹을 통해 응용 프로그램이 실제로 도움이되는지 아픈지 확인하십시오.


hibernate.order_inserts

Hibernate가 더 많은 일괄 처리가 사용될 수 있도록 삽입을 정렬하도록한다. 성능에 영향을 미치기 때문에 이전과 후에 벤치마킹을 통해 응용 프로그램이 실제로 도움이되는지 아픈지 확인하십시오.


버전 5.2부터, Hibernate는 주어진 JDBC hibernate.jdbc.batch_size설정 값에 의해 주어진 전역 JDBC 배치 크기를 오버라이드 (override) 할 수있다 Session.



----------------------------------------------------------------------


Hibernate는 새로이 삽입 된 모든 Customer인스턴스를 세션 레벨 c1ache에 캐시 하므로 트랜잭션이 끝나면 100000 개의 엔티티가 영속 컨텍스트에 의해 관리됩니다. JVM에 할당 된 최대 메모리가 다소 적 으면이 예제는에서 실패 할 수 OutOfMemoryException있습니다. Java 1.8 JVM은 사용 가능한 RAM의 1/4 또는 1Gb를 할당하여 힙에 100,000 개의 객체를 쉽게 수용 할 수 있습니다.


장기 실행 트랜잭션은 연결 풀을 고갈시켜 다른 트랜잭션이 처리 할 기회를 얻을 수 없습니다.


JDBC 일괄 처리는 기본적으로 활성화되어 있지 않으므로 모든 삽입 문에는 데이터베이스 왕복이 필요합니다. JDBC 배치를 사용하려면 hibernate.jdbc.batch_size속성을 10에서 50 사이의 정수로 설정하십시오 .



----------------------------------------------------------------------



EntityManager 사용 

public abstract class AbstractBulkRepository {

@Value("${spring.jpa.properties.hibernate.jdbc.batch_size:500}")
private int batchSize;

@Autowired
AdGroupJpaRepository adGroupJpaRepository;

@PersistenceContext
EntityManager entityManager;


public <T> int bulkDataSave(List<T> entities) throws DataAccessException {

AtomicInteger adGroupInsightIndex = new AtomicInteger(1);

entities.forEach(entity -> {

entity = entityManager.merge(entity);

//entityManager.setFlushMode(FlushModeType.COMMIT)
//entityManager.persist(entity);
if (adGroupInsightIndex.get() > 0 && adGroupInsightIndex.get() % batchSize == 0) {
entityManager.flush();
entityManager.clear();
}
adGroupInsightIndex.getAndIncrement();

});

entityManager.flush();
entityManager.clear();
//entityManager.close();

// 로그 용도
//entitys.get(0).getClass().getName()

return adGroupInsightIndex.get();

}



일반 JPARepository


@Autowired
AdGroupJpaRepository adGroupJpaRepository;

@Transactional(transactionManager = "transactionManager", propagation = Propagation.REQUIRED)
public boolean dataSave(List<AdGroupMeta> adSetOriginalMetaData) {

if (adSetOriginalMetaData == null) {
log.info("fbAdGroupMetaDataSave 데이터가 없습니다 ");
return false;
}

List<AdGroupEntity> adGroupEntityList = new ArrayList<>();
AtomicInteger adGroupInsightIndex = new AtomicInteger(1);

adSetOriginalMetaData.forEach(adSetMetaData -> {
try {

if (adGroupInsightIndex.get() > 0 && adGroupInsightIndex.get() % batchSize == 0) {


...


// AdGroup 데이터 저장
this.adGroupJpaRepository.saveAll(adGroupEntityList);
this.adGroupJpaRepository.flush();
adGroupEntityList.clear();

}
adGroupInsightIndex.getAndIncrement();

} catch (Exception e) {
e.printStackTrace();
}
});

this.adGroupJpaRepository.saveAll(adGroupEntityList);
this.adGroupJpaRepository.flush();

super.bulkDataSave(adGroupEntityList);

return true;
}





Properties

spring:
devtools:
restart:
enabled: false
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://IP:3306/DB_NAME?useUnicode=true&characterEncoding=utf8
username: id
password: password!@#
jpa:
generate-ddl: true
open-in-view: true
show-sql: true
hibernate:
ddl-auto: validate
database: mysql
database-platform: org.hibernate.dialect.MySQL5Dialect
properties:
hibernate.jdbc.batch_size: 200
hibernate.jdbc.batch_versioned_data: true
hibernate.order_inserts: true
hibernate.order_updates: true
hibernate.enable_lazy_load_no_trans: true
data:
jpa:
repositories:
enabled: true






---------------------------------------------------------------------------------

일괄 처리 공통 처리 부분 좋은 예제 


https://memorynotfound.com/hibernate-jpa-batch-insert-batch-update-example/

https://frightanic.com/software-development/jpa-batch-inserts/


하이버 네이트 배치 처리 설명 

http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#batch


---------------------------------------------------------------------------------

영속성 관리 참고 

http://cocomo.tistory.com/334

https://wckhg89.github.io/archivers/JPA

http://victorydntmd.tistory.com/207

https://www.slideshare.net/ssusere4d67c/jpa-53004111


---------------------------------------------------------------------------------

참고 https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/batch/Batching.html

0 Comments
댓글쓰기 폼