JPA 19

[SpringBoot] JPA 쿼리 성능 감시 가이드

개요 팀 내 JPA 쿼리 성능 감시 가이드를 작성하는 업무를 맡은 김에 간단하게 다음 항목을 정리해 보겠습니다. JPA slow 쿼리 검출 JPA N + 1 문제가 의심되는 api 검출 JPA N + 1 문제가 의심되는 api의 경우 범고래님 블로그를 많이 참고했습니다! 감사합니다. 프로젝트 환경 SpringBoot 2.6.3 Java 1.8 Jpa slow 쿼리 검출 application.yml에 다음과 같이 설정을 하면 Hibernate에서 slow query를 로깅해 줍니다. 테스트 삼아 100ms를 기준으로 잡았고 그 결과 실행시간이 205ms인 SELECT 쿼리가 아래와 같이 로깅되었습니다. 오래 걸린 쿼리를 로깅하는 것 자체는 좋았지만 구현한 JpaRepository가 워낙 많다 보니 검출된 ..

[DEV] 기록 2024.03.12

[Springboot] Jpa 프로젝트에 jOOQ 도입

jOOQ를 도입하게 된 배경 현재 진행하고 있는 프로젝트의 기술스택 중 이번 게시글과 연관된 기술들과 버전은 아래와 같습니다. Springboot 2.6.3 Java 1.8 spring-boot-starter-data-jpa (기본 키 생성 전략: IDENTITY) MariaDB 10.9.2 버전 QueryDSL 5.0.0 버전 Maven 프로젝트 내 기능 중 대용량 엑셀 업로드 기능과 json import 기능이 있는데 데이터가 커질수록 병목현상이 심해지는 것을 발견할 수 있었습니다. (json import의 경우 멀티 쓰레드 방식으로 과장님이 어느 정도 해결하시긴 하셨습니다.) 대용량으로 업로드할 때 entity를 하나하나 저장할 경우 불필요한 DB 커넥션이 많이 생기므로 1000개씩 묶어서 bulk..

리서치 2023.10.03

[Spring Data Jpa] java.lang.StackOverflowError

개요 JPA 객체를 저장하는데 아래와 같은 에러가 발생했습니다. java.lang.StackOverflowError: null at com.ecomhunt.entities.Order.hashCode(Order.java:15) ~[classes/:na] at java.base/java.util.AbstractSet.hashCode(AbstractSet.java:124) ~[na:na] at com.ecomhunt.entities.Customer.hashCode(Customer.java:11) ~[classes/:na] at com.ecomhunt.entities.Order.hashCode(Order.java:15) ~[classes/:na] at java.base/java.util.AbstractSet.h..

[DEV] 기록 2023.09.04

[JPA] Hibernate MultipleBagFetchException

개요 JPA 쿼리를 통해 엔티티를 불러올 때 두 개 이상의 @OneToMany 관계를 갖는 엔티티를 함께 EAGER LOADING 할 때 아래와 같은 오류 메시지가 발생했습니다. 저 같은 경우 위와 같이 @OneToMany 관계가 다수인 엔티티를 FETCH JOIN을 통해 한 번에 불러오려고 할 때 MultipleBagFetchException 예외가 발생했습니다. * SampleInput과 SampleOutput을 모두 fetch type EAGER로 변환한다고 해도 동일한 에러가 발생합니다.) 원인 위와 같은 예외가 발생하는 원인을 파악하기 위해서는 우선 Bag의 정의를 살펴봐야 합니다. Bag은 중복된 요소를 허용하는 순서가 없는 컬렉션(MultiSet)이며 Java Collection에서는 Ba..

DB/JPA 2023.06.28

[Springboot] 멀티 데이터소스 (MyBatis, JPA)

개요 최근 회사 업무를 하며 멀티 테넌시 아키텍처를 적용한 서비스를 개발했습니다. 요구사항은 아래와 같았습니다. 사용자 로그인 정보를 토대로 해당 tenant에 매핑된 데이터베이스와 연동 런타임에 테넌트 추가 가능 즉, 재기동 없이 동적으로 사용자와 사용자가 매핑된 데이터소스를 추가 가능 테넌트를 추가할 때 데이터베이스 및 테이블 자동 생성 클라우드 시장이 성장함에 따라 멀티 테넌시를 지원하는 XaaS가 늘어날 것으로 판단되기 때문에 해당 내용을 다루고 싶었고 생각보다 코드 레벨까지 설명해 주는 글이 별로 없었기 때문에 개인적으로 정리해 보겠습니다. 멀티 테넌시 아키텍처 중 멀티 데이터소스를 집중적으로 다룰 예정이고 기타 예외처리 및 인증/인가 설정은 주제에 벗어나기 때문에 생략하도록 하겠습니다. (구현..

리서치 2023.03.25

[SpringBoot + JPA] @NamedEntityGraph

개요 현재 프로젝트 내 JPA 글로벌 Fetch 타입은 Lazy이지만 특정 페이지에서는 연관관계가 있는 객체들을 모두 불러와야 하는 경우가 있어 Lazy Loading으로 N번 쿼리를 호출하는 것보다 한 번에 가져오는 것이 성능이 좋을 것이라고 판단했습니다. 찾아본 결과 @NamedEntityGraph 어노테이션을 사용하면 특정 JPA 쿼리에 대해 커스텀 Fetch 타입을 정의할 수 있다는 것을 알았고 저는 위 문제를 해당 어노테이션을 통해 해결했습니다. 예제 Example.class Example.class와 연관된 엔티티가 3개 있다고 가정 @OneToMany, @ManyToMany 연관관계는 디폴트 Fetch 타입이 Lazy 특정 페이지에서는 해당 엔티티들의 정보가 모두 필요하므로 Lazy Load..

[DEV] 기록 2022.04.10

[SpringBoot] 구글 SMTP 통해 메일 보내기

개요 회원 가입 이후 이메일 인증을 한 사용자에게만 서비스 접근을 할 수 있도록 구현하고 싶어 찾아본 결과 구글에서 제공하는 SMTP 서비스를 통해 비교적 쉽게 구현할 수 있었습니다. 단, 구글 SMTP 서비스는 한 이메일 당 하루 100건씩 제한을 걸기 때문에 로컬에서 여러 번 테스트하고 싶을 때는 실제 메일을 보내지 않고 콘솔에 메일 내용을 로그로 작성하는 것을 추천드립니다. 이번 게시글에서는 구글 SMTP 설정과 메일 보내는 방법 그리고 콘솔에 메일 내용을 로그로 작성하는 방법을 간단히 공유해보겠습니다. 1. 구글 계정 앱 비밀번호 설정 및 application.properties 설정 구글 SMTP를 사용하기 위해서는 구글 계정 내 앱 비밀번호를 설정해야 합니다. https://support.go..

Spring 2022.04.10

[SpringBoot] OpenSessionInView

개요 JPA를 사용하는 서비스를 개발하는 도중 Controller에서 데이터를 변경했는데도 불구하고 DB에 변경이 되지 않는 문제가 발생했습니다. 검색해보니 이는 Transactional 범위 밖에서 데이터를 변경했기 때문에 발생했던 문제이고 자세한 내용을 알기 위해서는 OpenSessionInView(OSIV) 동작 원리를 알아야 한다고 해서 간단히 정리해보겠습니다. (OSIV는 hibernate에서 사용하는 용어이고 사실 JPA에서는 OpenEntityManagerInView(OEIV)라고 지칭합니다.) 내용을 잘 정리해주신 Shi._.D TIL님께 감사드립니다. * 해당 글은 JPA 영속성 컨텍스트에 대해 안다는 전제 하에 작성했습니다. https://jaimemin.tistory.com/1898 ..

Spring 2022.03.29

[JPA] JPQL 추가 정리

개요 지난 게시글(https://jaimemin.tistory.com/1997)에 이어 아래의 JPQL 개념에 대해 정리해보겠습니다. 경로 표현식 Fetch Join 엔티티 파라미터 Named 쿼리 벌크 연산 1. 경로 표현식 엔티티의 getter와 동일한 개념 ex) SELECT e.id FROM Employee e e.id와 같이 .을 찍어 객체 그래프를 탐색하는 것을 경로 표현식이라고 함 경로 표현식은 3가지 종류가 존재 상태 필드 단일 값 연관 필드 컬렉션 값 연관 필드 1.1 상태 필드(state field) 단순히 값을 저장하기 위한 필드 (e.name과 같은 필드) 경로 탐색의 끝 즉, 이후에 더 이상 점을 찍을 수 없음 ex) SELECT e.name, e.age FROM Employee ..

DB/JPA 2021.10.18

[JPA] JPQL 간단 정리

개요 JPA는 아래와 같이 다양한 쿼리 방법을 지원합니다. JPQL JPA Criteria QueryDSL Native SQL JDBC API 직접 적용 이번 게시글에서는 간단하게 위 쿼리 방법들을 설명한 후 JPQL 기본 문법과 기능에 대해 알아보겠습니다. 1. 다양한 쿼리 방법 소개 1.1 JPQL JPA가 테이블이 아닌 엔티티 객체를 중심으로 개발하는데, JPQL 역시 엔티티 객체를 대상으로 검색하는 쿼리 방법 (객체지향적인 것이 핵심) JPQL은 SQL을 추상화한 객체 지향 쿼리 언어 실제로 SQL 문법과 유사하여 ANSI 표준 키워드 전부 지원 (SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN) 앞서 언급한 대로 JPQL은 엔티티 객체를 대상으로 쿼리 반면, SQL..

DB/JPA 2021.10.16