Hibernate 특징
Hibernate는 새로이 삽입 된 모든 Customer인스턴스를 세션 레벨1 cache에 캐시 하므로 트랜잭션이 끝나면 100000 개의 엔티티가 영속 컨텍스트에 의해 관리됩니다. JVM에 할당 된 최대 메모리가 다소 적 으면이 예제는에서 실패 할 수 OutOfMemoryException있습니다. Java 1.8 JVM은 사용 가능한 RAM의 1/4 또는 1Gb를 할당하여 힙에 100,000 개의 객체를 쉽게 수용 할 수 있습니다.
장기 실행 트랜잭션은 연결 풀을 고갈시켜 다른 트랜잭션이 처리 할 기회를 얻을 수 없습니다.
JDBC 일괄 처리는 기본적으로 활성화되어 있지 않으므로 모든 삽입 문에는 데이터베이스 왕복이 필요합니다. JDBC 배치를 사용하려면 hibernate.jdbc.batch_size속성을 10에서 50 사이의 정수로 설정하십시오 .
일괄 처리 속성 (Hibernate. properties)
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 / JPA 두가지 방식을 소개 한다.
1. Hibernate 방식 - 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();
}
2. 일반 JPARepository
일반 JPA Repository로 일괄 업데이트 저장을 하기 위해서는 하이버 네이트 설정을 추가해 주어야 한다.
application.yml 의 hibernate property 에 몇가 지 속성을 추가한다. (위에 일괄처리 속성 참고)
hibernate.jdbc.batch_size: 200 # 배치사이즈 설정
hibernate.jdbc.batch_versioned_data: true # 에러가 났을때 잘못된 행수 반환 여부
hibernate.order_inserts: true # insert 구문을 묶어서 일괄처리 함
hibernate.order_updates: true # update 구문을 묶어서 일괄처리함
2.1 bulkClass 예제
public class bulkClass {
@Autowired
AdGroupJpaRepository adGroupJpaRepository;
@Transactional(transactionManager = "transactionManager", propagation = Propagation.REQUIRED)
public boolean dataSave(List<AdGroupMeta> adSetOriginalMetaData) {
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();
return true;
}
}
2.2 allpication.yml 설정
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
'Spring > Spring Data JPA' 카테고리의 다른 글
QueryDsl Projection.bean Object로 조회 결과 받기 (0) | 2019.08.26 |
---|---|
Hibernate/ spring jpa bulk save (0) | 2019.03.26 |
JPA Hibernate Multi PK 주의점 (정적 내부 클레스) (0) | 2018.10.08 |
@OneToOne 양방향 매핑 주키(PK)공유 (0) | 2017.09.27 |
Jpa JSON 순환참조 @ResponseBody (0) | 2017.09.21 |