강의

멘토링

로드맵

Inflearn brand logo image

인프런 커뮤니티 질문&답변

HAHA님의 프로필 이미지
HAHA

작성한 질문수

실전! 스프링 데이터 JPA

벌크성 수정 쿼리

bulk insert 질문입니다.

작성

·

101

0

안녕하세요.

bulk insert 관련해서 궁금한점이 있습니다.

사실상 데이터베이스를 다룰 때 IDENTITY를 거의 사용할 것이라고 생각합니다.

이럴 경우 bulk insert를 어떻게 처리해야 될 지 궁금합니다.

다른 질문에 답변을 봤을때 책에 나온 쓰기 지연같은 경우도 IDENTITY에서는 안되는 것이라고 알고 새로운 질문을 드립니다.

IDENTITY 키를 가진 엔티티들 bulk insert를 하기 위해 JdbcTemplate가 최선이다 까지 이해했습니다.

 

예를 들어 상품을 등록할때 상품과 카테고리들 이미지들을 저장한다고 생각해보겠습니다.(각각 다른 테이블 및 1:N)

이런 경우 상품에 새로운 엔티티들을 만들고 save를 호출할 경우 IDENTITY를 가진 엔티티들이니 각 쿼리들이 따로 다 날라갑니다.

그래서 JdbcTemplate를 사용해 카테고리들과 이미지들을 batch insert할 경우
기존 엔티티에 정보를 어떻게 관리하는지 궁금합니다.

 

jdbcTemplate로 bulk insert한 경우 id를 받아오지 못하는 것으로 알고 있는데, 이런 경우 jdbcTemplate으로 값을 넣은 후에

기존 상품 엔티티에서 카테고리 혹은 이미지들에 접근할 경우 lazy 기능이 동작하지 않을 것이라 생각되는데 실무에서는 bulkInsert하는 경우 lazy하는 값에 접근하지 않는다. 이런 약속을 정해놓고 개발하시는건가요?

아니면 batchInsert로 넣는 값들은 내부에서 가지고 있지 않고 추후에 조회할때 조인도 사용하지 않으시나요?

 

질문 의도는 결국 IDENTITY인 경우 batch insert를 어떻게 해야 좋은 것이고, 만약 jpa에서 처리가 안될 경우(JdbcTemplate 등을 사용) 영속성 컨텍스트와 어떻게 문제가 생기지 않고 처리하시는지 궁금해 질문드렸습니다.

제 짧은 생각으로는 어떻게든 영속성 컨텍스트 문제가 생길 것 같은데, 실무에서는 그럼 이런 엔티티는 드무니까 save 코드 주석으로 특정 lazy 값에는 접근하지 말라는 내용을 써놓고 컨벤션 느낌으로 개발하시는지도 궁금합니다.

jpa, data jpa와 querydsl 강의를 모두 수강하였기 때문에 jpa에서만 국한되어 답변해주시지 않고 data jpa, querydsl, JdbcTemplate 혹은 다른 방법 어떤 내용을 포함해주셔도 공부하고 이해할 수 있습니다.

 

항상 좋은 강의 감사드립니다.

답변 2

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. HAHA님

JPA 가 아닌 기술로 어떤 데이터를 변경한 경우에 JPA 영속성 컨텍스트와 맞지 않는 문제가 발생할 수 있습니다. 이런 경우 대부분 영속성 컨텍스트를 초기화하고, 필요한 데이터를 다시 조회하는 방식으로 문제를 해결합니다 🙂

감사합니다.

HAHA님의 프로필 이미지
HAHA
질문자

답변해주셔서 감사합니다.

일반적으로 볼 때 컨트롤러에서 EntityManager를 접근하지 않게 레이어를 분리하는 것으로 알고 있습니다.

이런 경우 어쩔 수 없이 EntityManager를 controller에서 인자로 가지고 있고 flush와 clear를

jdbcTemplate을 사용하는 service 메서드 호출 전에 호출하는게 좋다 라는 뜻으로 말씀하신건지 궁금합니다.

아니면 실무에서는 jdbcTemplate을 사용하는 곳을 주석으로 가르고 여기부터는 jpa domain 영속성 컨텍스트 사용하지 않게 코드 내에서 컨벤션을 정해 놓고 구현하시는지 궁금합니다.

제가 경험이 부족하여 개념상으로는 이해하지만 실제로 코드를 어떻게 실무에서 구현하시는지 예상이 가지 않아 한 번 더 여쭤봅니다.

감사합니다.

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. HAHA님

보통은 컨트롤러 -> 서비스 -> 리포지토리를 호출합니다.

이런 경우 3가지 해결방안이 있는데요.

  1. 리포지토리에서 JdbcTemplate을 사용한 다음에 그곳에서 EntityManager를 클리어합니다.

  2. 서비스 계층에서 EntityManager를 주입받고 그곳에서 EnttiyManager를 클리어합니다.(서비스 계층이 EntityManager에 의존하는 단점이 있겠지요?)

  3. @EntityManagerClear 같은 AOP를 하나 만들고 리포지토리의 특정 메서드에 지정합니다. 이 AOP는 해당 리포지토리 실행 이후에 EntityManager를 클리어합니다.

이런 경우가 거의 없다면, 단순함의 관점에서 1, 2번 중에 하나를 선택하시면 되고, 이런 경우가 자주 발생한다면 3번을 선택하시면 됩니다.

감사합니다.

 

 

0

안녕하세요, 인프런 AI 인턴입니다. HAHA님.

IDENTITY 전략을 사용할 때 벌크 인서트에 대한 고민은 많은 개발자들이 마주하는 문제입니다. IDENTITY 전략은 각 엔티티가 데이터베이스에 삽입될 때마다 새로운 아이디 값을 생성하기 때문에, 벌크 인서트의 효과를 제한할 수 있습니다. 따라서 대량의 데이터를 효율적으로 삽입하기 위해 몇 가지 접근 방식을 고려할 수 있습니다.

  1. JdbcTemplate을 활용한 벌크 인서트: IDENTITY 전략을 사용하면 한 번에 여러 레코드를 삽입하는 것이 어렵습니다. 따라서 JdbcTemplate을 사용하여 직접 SQL 쿼리를 생성하고 실행하는 것이 일반적인 해결 방법입니다. 이 방법을 사용할 경우, 삽입 후 생성된 키를 별도로 관리해야 한다는 점에서 약간의 복잡함이 있습니다.

  2. 영속성 컨텍스트 관리: JdbcTemplate로 삽입된 데이터는 JPA의 영속성 컨텍스트와 무관하기 때문에, 해당 데이터가 필요할 때는 다시 조회해야 합니다. 실무에서는 이러한 상황을 피하기 위해, 삽입 후 즉시 해당 데이터를 다시 조회하고 필요한 엔티티에 반영하는 방법을 사용하거나, Lazy 로딩이 적용되지 않는 방식을 고려할 수 있습니다.

  3. JPA와의 결합 방지: 말씀하신 것처럼, 영속성 컨텍스트와의 문제를 피하기 위해 벌크 인서트된 데이터는 주의하여 다루어야 합니다. 일반적으로 중요한 부분은 벌크 인서트로 추가된 데이터는 되도록 영속성 컨텍스트에서 관리하지 않아야 하며, 필요한 경우에만 조회하여 사용하도록 하는 것이 건강한 접근 방법입니다.

관련 질문과 답변은 다음 게시물에서도 확인할 수 있습니다:

이러한 접근 방법을 통해 IDENTITY 전략을 사용하면서도 효율적인 데이터 삽입을 수행할 수 있을 것입니다. 더 궁금한 사항이 있다면 언제든지 추가 질문해 주세요. 감사합니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

HAHA님의 프로필 이미지
HAHA

작성한 질문수

질문하기