JPA
5 posts
[JPA] @Transactional이 없다고 레포지토리가 왜 터져?

🧶 문제상황 서버 오픈 전 부하테스트로 대비하기의 경험으로, 요즘 코드를 짤 때 외부 호출이 끼어있다면 트랜잭션을 최소로 잡고 있다. 거기다 더티 체킹도 사용하지 않고 명시적으로 다시 저장해주는 방식을 사용 중이다. 이건 교휸이 있어서는 아니고, 그냥 성향이다. 더 읽기 명확한 것 같고? 여기에 아이템을 삭제하는 기능을 추가 개발하게 되었다. 그리고 테스트를 실행하니, 아래와 같은 에러 메시지를 던지며 터졌다. No EntityManager with actual transaction available for current thread - cannot reliably process ‘remove’ call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably…

May 07, 2023
JPA
트러블슈팅
[JPA] 실종된 데이터와 연관 객체 조회하기

백엔드 면접 단골 질문 중 하나가 이다. 물론 몇 달 전까지 나도 줄줄 외우고 있었다. dto로 갖고 오던가, 페치 조인이 엔티티 그래프가 어쩌고 배치 사이즈를… 그리고 몇 개는 실제로 적용해서 문제를 해결해보기도 했지만, 비교적 전형적인 케이스만 다뤘기에 적용했더니 해결됐다, 끝! 이었다. 그래서 최근에 을 해결하기 위해 페치 조인을 쓰다가 동작을 잘 모른다는 걸 알게 되었다. 🎁 문제 상황 단방향 연관관계를 가진 두 엔티티가 있다. 는 유저가 획득한 아이템이다. 는 아이템을 획득, 또는 사용될 때 생기는 로그다. 엔티티 , 는 다음과 같은 비즈니스 로직을 가진다. 아이템 로그는 아이템에 취한 행동에 따라 , 이 정해진다. 아이템 획득은 -> 순서로 이뤄진다. 이 후 까지 로직에서 문제가 생기더라도, 은 남아야 한다. 따라서 는 아이템 로그를 가지지 않을 수도 있다. 두 엔티티는 단방향 간접참조로 연결되어있다. 아이템 로그는 아이템 획득 엔티티를 모른다. DB에는 두 테이블…

March 26, 2023
트러블슈팅
JPA
[JPA] EnableJpaAuditing의 내부와 CI의 소중함

💣 문제상황 줍줍에는 북마크 설정한 메시지를 모아서 보는 기능이 있다. 기존에는 이 북마크 목록을 보여줄 때, 북마크가 등록 된 메시지의 생성 시간 순서대로 보여줬다. 그러다 사용자 편의를 위해 이를 북마크 등록 시간 순서대로 보여주기로 바꿨다. 이 때, 북마크 등록 시간을 편하게 관리하기 위해 을 도입했다. 그리고 해당 PR은 순조롭게 머지 되었는데… 팀원 봄이 진행한 컨트롤러 테스트를 WebMvcTest로 개선하는 PR에서 문제가 생겼다. 봄의 로컬에서 테스트가 잘 돌아가는 상태였는데, PR의 github action에서는 테스트가 실패했다. 로 변경한 모든 용 컨트롤러 테스트가 같은 이유로 실패하고 있었다. 라는 문구가 눈에 띈다. 해당 문구로 라이브러리를 검색해보면 라는 클래스가 나온다. 사실 이 문구로 검색하면 많은 사람들이 해결법을 이미 올려두었다. 그런데 여기까지 오니, 이 대체 뭔데? 도 아니고 라고? 이거랑 은 무슨 상관이지? 등등 궁금한 점이 생겨서 코드를 조금…

October 14, 2022
Spring
JPA
트러블슈팅
[JPA]는 새로운 엔티티를 어떻게 알아볼까?

Long id = 0L ? 코틀린을 공부하다 참고하려고 우테코 지원 플랫폼의 코드를 봤다. 그 중 흥미로운 점을 발견했는데, 엔티티를 생성할 때 를 로 초기화 하는 것이다. 이게 왜 흥미로웠냐면 상수 픽스쳐 사용 주의 포스팅에서 썼듯이 가 이 아니면 를 시행한다고 생각했기 때문이다. 굳이 로 초기화하면 비용만 추가로 들 것 같았다. 그래서 자바 스프링에서 직접 간단한 엔티티를 만들고, id를 로 지정해 저장해봤다. 실행된 SQL문을 보면, 역시나 문이 문에 선행되었다. 대신 가 수행된 것이다. JPA의 새로운 엔티티 식별법 상속 시 쓰게 되는 구현체인 의 를 다시 살펴보자. 참 명료한 언어로 잘 짜여있다. 니까 엔티티가 새로운 엔티티라면 를, 아니라면 를 수행한다. 그렇다면 이 는 어디서 가져오는 걸까? 를 구현한 몇 개의 클래스에 디버깅을 걸며 찾아보니 라는 낯선 이름의 클래스에 걸렸다. 코드 상 를 판단하는 조건은 다음과 같다. 엔티티의 가 원시 타입이 아니라면 일 때 …

August 24, 2022
JPA
kotlin
[JPA] 상수 픽스쳐 사용 주의

문제상황 우테코 QNA 미션에서 상수로 선언된 엔티티 픽스쳐가 있었다. 레벨3 같은 팀 크루인 봄이 해당 미션을 진행하다 테스트가 터져 어쩌다보니 같이 원인을 찾게 되었다. 상황을 비슷하게 복구해보자면 이런 구성이었다. 원본 미션 코드에서는 픽스쳐가 로 별도 클래스에 선언되어 있었다. 그런데 테스트 클래스 하나에서만 사용되고 있어서 해당 클래스로 옮겼던 것 같다. 나도 픽스쳐를 옮겼다가, 평소 쓰는 방식대로 한다고 지웠었다. 어쨌든 와 는 의 단방향 연관관계였고, 는 를 통해 저장해주는 상태였다. 그러다 테스트가 터지며 의문의 에러메시지를 마주했다. org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [FK83S99F4KX8OIQM3RO0SASMPWW]; nested exception is org.hibernate.exception.Con…

August 13, 2022
JPA
트러블슈팅