JPA
6 posts
하이버네이트 default-batch-fetch-size 가 안되는 현상 😢

💡 Intro JPA를 프로젝트에서 사용하면서 연관 엔티티를 호출할 때 생기는 N+1을 해결한 경험이 있다. 이때 해결 방법으로 hibernate의 를 yml에 설정하여 해결했었다. 참고링크 해결부분 프로젝트를 전반적으로 체크하던 와중에 위 설정에 의한 in query가 실행되지 않고 여전히 N+1 문제가 발생하는 부분을 발견하였다. 해당 현상을 공유하기 위해 글을 작성한다. (여전히 이유는 못 찾았다 😢) 🌩 우선 간단하게 위 설정에 대해서 짚고 넘어가보자. 설정할 수 있는 방법은 두 가지 이다. 어노테이션 활용 클래스, 메소드, 필드 레벨에서 사용할 수 있다. 해당 사이즈 만큼의 상위 엔티티 id가 in query로 나간다. 를 application.properties에 지정 전역적으로 적용이 되어서 상위 엔티티의 lazy loading된 하위 엔티티를 한꺼번에 in query로 로딩한다. Hibernate javadocs 공식 문서에 다음과 같이 서술한다. 즉, 속한 co…

October 21, 2021
JPA
프로젝트
JPA 에서 별칭을 쓰지 않는 이유 (하지만 쓴 이유)

Intro JPA의 사용시 별칭을 쓰면 안되는 이유가 무엇인지 알아본다. 프로젝트애서 fetch join 시 별칭 사용에 대해서 고민해본다. fetch join 별칭은 왜 안될까 ? fetch join에서 별칭이 안되는 이유는 데이터의 일관성이 깨지기 때문이다. 예를 들어서 다음과 같은 코드는 fetch join 대상에 조건문이 들어가서 일관성이 깨진 경우이다. TeamA에 대한 member collection 은 본래 3개이다. 그리고 fetch join을 하면 연관된 데이터가 모두 들어올 것이라고 가정한다. 하지만 위와 같이 fetch join 대상에 별칭을 주어 where 필터링 조건을 사용하면 실제로 TeamA에 연관된 멤버는 3명이지만 만 연관 데이터로 들어온다. DB의 상태에 대한 일관성이 깨진다. 하지만 예외는 있다 일관성을 해치지지 않는 한에서 성능에 도움이 된다면 예외적으로 사용해도 된다. (아마도 하이버네이트가 별칭을 허용하는 이유…) 예를 들어 다음과 같은 쿼…

October 06, 2021
JPA
프로젝트
JPA N+1 문제 및 해결방법 알아보기

INTRO JPA에서는 데이터와 객체지향으로 설계 사이의 모순을 해소하기 위해서 나온 기술이다. 많은 객체들은 내부에 Collection 형태로 다른 객체에 대한 참조가 가능하게 설계된다. 예) 객체 내부에 에 속해있는 와 팀에 할당된 가 존재한다. 이때 상위 객체를 select 하면서 하위 객체를 가져오는 경우 다음 두가지 fetch 타입에 각각 다음과 같은 문제가 있다. 일 경우 : 이 발생 일 경우 : 문제 발생 상위 엔티티에서 다수의 collection 형태의 연관엔티티를 가지고 있을 때 여러 상황 및 문제와 해결 방법에 대해서 공부해본다. Entity 상황 과 가 1:N 연관관계 - , 과 가 1:N 연관관계 - , 참고 : 우선 모든 연관관계는 로 적용하고 테스트 상황에 따라 로 변경 엔티티 엔티티 엔티티 JPA에서 collection fetch join Team에 대한 모든 정보가 필요한 경우 Team을 가져오면서 Members와 Lockers 정보도 모…

August 26, 2021
JPA
JPA 프록시 관련 버그 경험기

INTRO JPA 에서는 데이터베이스에서 연관객체 탐색을 효율적으로 하기 위해서 지연로딩 전략을 사용한다. 지연로딩의 핵심은 연관관계에 있는 Entity가 실제로 사용되기 이전까지 DB에 실제로 참조하지 않고 프록시 객체로 대체하는 것이다. JPA의 프록시 객체는 유용하지만 내부 동작방식에 대해서 제대로 알고있지 않으면 찾기 어려운 버그를 만날 수도 있다. 다음은 JPA proxy 관련해서 프로젝트 진행시 만난 버그에 대한 내용이다. 문제 상황 Entity 구조 참고: 설명과 관련된 부분만 남기고 다른 로직 및 어노테이션은 대부분 생략했다. - 게시물 엔티티 와 - Post 엔티티 하위의 Embedded 게시물 Like collection 포장객체 참고: 설명하고자 하는 부분과 깊게 연관된 핵심 Entity는 아니지만 상황 설명을 위해 간단히 프로퍼티만 소개한다. - 어플리케이션 사용자 (게시물 좋아요, 유저간 팔로우 팔로잉 등의 행위를 함) 와 - 해당 의 팔로워리스트…

August 26, 2021
JPA
프로젝트
JPA 프록시 알아보기

INTRO JPA는 DB의 데이터와 객체간의 모순을 해결하기 위해서 나온 것이다. 객체는 객체 그래프로 탐색이 가능하지만 데이터베이스에 저장된 데이터는 객체를 탐색하듯이 탐색하기가 어렵다. 따라서 데이터베이스에 저장된 데이터들을 가지고 객체 그래프 탐색이 가능하기 위해서 프록시 라는 기술이 나왔다. JPA에서는 연관된 객체를 로딩하는데 지연 로딩과 즉시 로딩이라는 두가지 기법을 사용한다. 여기서 지연 로딩시 프록시 기술이 사용된다. 기본 예시 Entity Member Team 프록시 지연 로딩을 설정된 연관 객체를 가져올 때 프록시 객체를 가져온다. 를 사용하면 실제 객체를 가져오고, 를 사용하면 프록시 객체를 가져온다. 프록시 객체를 가져온다는 것은 query는 실행되지 않는 것이다. 특정 객체에 대해 를 하면 연관된 객체에 대해서는 설정되어 있는 종류에 따라 즉시로딩 혹은 지연로딩한다. 실제 Entity 조회 - 위 테스트를 실행하면 다음과 같은 select 쿼리가 실행된다…

August 26, 2021
JPA
LazyInitializationException 란?

LazyInitialization 에러 발생 이유 Lazy Loading을 하려고 하는데 세션이 사라져서 프록시 초기화가 불가능해 지연로딩을 못하는 경우에 발생하는 에러 가장 단순한 방법으로는 을 로 설정해서 일괄적으로 부모 호출시 자식이 모두 즉시로딩으로 초기화되도록 하면 되지만, 비니지스적인 이유가 아닌 을 피하기 위해 로 설정하는 것은 좋지 않다. 위 에러는 Lazy Loading을 하는 시점까지 session을 유지시켜주는 것이 핵심이며 주로 추가로 해당 문제는 해결된다. 서비스 외부에서 LazyLoading Collection 호출 시 서비스에서 LazyLoading을 하고 싶다면 을 붙여서 해결할 수 있지만 간혹 서비스 클래스 밖에서 지연로딩 지정되어 있는 컬렉션을 조회해야할 때가 있다. 그럴 때 에러를 피할 수 있는 방법은 두가지이다. 1. 를 사용해 서비스 내에서 조회 만일 서비스가 아닌 다른 클래스 내에서 JPA 조회를 하고 싶다면 세션이 유지되지 않는다. …

August 04, 2021
JPA