@GeneratedValue(strategy = GenerationType.IDENTITY) 으로 선언된 PK가 있다면 JPA에서는 Bulk Insert를 지원하지 않습니다. QueryDSL-JPA도 마찬가지인데요. 이럴 경우 MyBatis나 JdbcTemplate을 사용해야 하는데 둘 다 타입 안정성이 떨어지지만 JdbcTemplate이 컴파일 타임 시 타입 안정성을 더 높일 수 있다고 판단하여 JdbcTemplate으로 Bulk Insert를 구현하게 됐습니다. JPA에서 Bulk Insert를 지원하지 않는 이유@GenerationValue(strategy = GenerationType.IDENTITY)로 @Id 컬럼을 선언하고 batch insert는 할 수 없습니다. 공식 문서에는 다음과 같..
![](http://i1.daumcdn.net/thumb/C148x148.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/c9LgsN/btsK01FCzEd/2b1SmFR0OYo1rBy78gcxnk/img.png)
Spring Boot 1.4.6.RELEASE 버전에서 개발을 진행하고 있었습니다.album과 song이라는 테이블이 있고 song은 외래키를 가지고 있는 주 테이블이며 album은 대상 테이블입니다. 아래는 클래스 코드입니다.@Data@Entitypublic class Album { ... @OneToMany(mappedBy = "album") private List songList = new ArrayList(); ... }@Data@Entitypublic class Song { ... @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "album_id", referencedColumnName = "id") ..
![](http://i1.daumcdn.net/thumb/C148x148.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/cpsSZa/btsKLoWD166/4BhDGFQKjf2aEbMQkcMclk/img.png)
JPA 1차 캐시와 2차 캐시에 관해서는 이 글을 읽기 전에 한 번 읽어보시길 추천드립니다. 클라이언트의 요청에 의해 영속성 컨텍스트의 스냅샷을 통한 1차 캐시는 그 생명주기가 OSIV인 경우 요청이 끝날 경우에 사라집니다.(OSIV가 아닌 경우 트랜잭션이 종료되면 영속성 컨텍스트가 종료될 때 같이 사라집니다.)그렇다면 매번 반복된 요청이 들어올 때 불필요한 디비 컨넥션 처리가 이루어지지 않도록 2차 캐시를 이용하여 효율성을 높이는 것이 좋다고 생각이 됩니다. 2차 캐시를 적용해서 한번 로직을 구성해 보겠습니다.@Overridepublic List findByTop100Song() { return jpaQueryFactory.selectFrom(song) .where(song.i..
![](http://i1.daumcdn.net/thumb/C148x148.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/r8BJX/btsKEmQywB9/kNIQjjCSPa7Wdcq0nehQa1/img.png)
네트워크를 통해 데이터베이스에 접근하는 시간 비용은 애플리케이션 서버에서 내부 메모리에 접근하는 시간 비용보다 수만에서 수십만배 이상 비쌉니다. 따라서 조회한 데이터를 메모리에 캐시해서 데이터베이스 접근 횟수를 줄이면 애플리케이션 성능을 획기적으로 개선할 수 있습니다. 영속성 컨텍스트 내부에서 엔티티를 보관하는 저장소가 있는데 이것을 1차 캐시라고 합니다.일반적인 웹 애플리케이션 환경은 트랜잭션을 시작하고 종료할 때까지만 1차 캐시가 유효합니다. 하이버네이트를 포함한 대부분의 JPA 구현체들은 애플리케이션 범위의 캐시를 지원하는데 이것을 공유 캐시 또는 2차 캐시라 합니다. 1차 캐시1차 캐시는 영속성 컨텍스트 내부에 있으며 엔티티 매니저로 조회하거나 변경하는 모든 엔티티는 1차 캐시에 저장..