반응형

JPA 23

[Hibernate] fetchJoin 시에 중복문제, 페이징을 사용하는 경우엔 미발생?

fetchJoin을 하는 경우, 카테시안 곱으로 인해 중복 문제가 발생한다.아래와 같이 클라이밍 팀 관련 데이터가 존재한다고 해보자.1팀, 2팀은 클라이밍고수 라는 동일한 팀 이름을 가지고 있다.(2팀에 계신 분들은 국가대표 선수들이라 진짜 고수고, 1팀은 클라이밍 고수가 되고 싶은 팀이라고 하자 ㅎㅎ) querydsl 메서드아래 querydsl 코드로 '팀이름으로 해당 팀의 회원 명단을 반환'하는 메서드를 생성했다.12345678@Overridepublic ListTeam> findAllMembersByTeamName(String teamName) {    return jpaQueryFactory.selectFrom(team)                          .join(team.member..

[Spring Data JPA] Custom Repository 구현체 클래스명 주의점

Spring Data JPA 를 사용한다면 (특히 querydsl) 아래와 같은 생각이 들 때가 있다. '클래스명 xxxRepositoryImpl 말고 xxxRepositoryImplementation 이라든지, HappyRepositoryImpl 처럼 좀 줄이거나 바꿔서 작성할 수 없나?' 안된다. 아래 에러를 만나게 된다. Failed to load ApplicationContextCaused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name defined in file  빈을 아예 못찾아서 위 에러가 발생하게 된다.원인을 찾기 위해 내려보면, No property foun..

[Spring] ArgumentResolver 사용 시 주의점 (feat. OSIV)

ArgumentResolver는 컨트롤러 단에서 요청값으로부터 원하는 객체 또는 프로퍼티를 반환하게 할 수 있다. 보통은 커스텀 유저 객체를 반환할 때 HandlerMethodArgumentResolver의 구현체를 이용하여 많이 사용한다. Java에서의 ArgumentResolver 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Component @RequiredArgsConstructor public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver { private final JwtTokenProvider jwtTokenProvider; @Ov..

[ERROR] JPA initializationError 해결 방법 모음 및 대처법

스프링 프레임워크에서 JPA ORM을 이용하면 반드시 한 번쯤은 만날 수밖에 없는 에러가 있다. could not prepare statement; SQL; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement at org.springframework.orm.jpa..

[JPA] 프로젝트 동시성 이슈 해결을 위해 낙관적 락을 걸어보았다

롤링페이퍼 기반 서비스 플랫폼을 개발하던 중 아래 버그를 발견했다. ??? 대체 어떤 일이 일어난다는 거야... 하는 마음으로 같은 메시지를 막 광클했을 때 위와 같이 `에러가 발생했어요` 페이지가 뜨는 것을 발견했다. 해당 메시지에 좋아요를 광클하거나, 같은 계정으로 PC/모바일 등 다중 환경 접속 후 좋아요를 여러번 동시에 누르면 발생하는 버그였다. 즉, 동시성 이슈로 발생한 문제였다! 우리 서비스에서는 한 명의 회원이 같은 메시지에 좋아요를 2개 이상 누를 수 없다. 인스타나 페이스북처럼 좋아요가 눌러진 상태에서 좋아요를 또 누르면 좋아요 취소가 작동돼야 한다. 하지만 위와 같이 광클하는 경우에는 그 찰나에 같은 회원의 메시지 좋아요가 2개 들어가버린 것을 확인할 수 있었다. 상황을 그림으로 정리해..

[QueryDSL] queryDSL 프로젝트 적용 후기 및 트러블슈팅

우테코 프로젝트에서는 Spring Data JPA를 사용하고 있었다. Spring Data JPA를 이용하면 인터페이스 생성 만으로도 SimpleJpaRepository에 내장된 다양한 CRUD 메서드를 활용할 수 있고, 추가로 커스텀 메서드도 편리하게 만들 수 있다는 장점이 존재한다. 그러나 Spring Data JPA는 동적 쿼리를 사용하기 어렵고 복잡한 쿼리는 @Query 어노테이션을 이용하여 JPQL을 직접 작성해주어야 한다는 문제점이 존재한다. 따라서 이번 기회에 queryDSL을 적용하여 컴파일 시점에 문법 오류를 잡아낼 수 있게 하고, 복잡한 쿼리를 리팩터링하는 데에 도전해보았다. 특히 위처럼 DTO를 반환하는 repository method의 경우 @Query로 작성하면 DTO 패키지명을 ..

[JPA] 벌크 Update, Delete 연산과 영속성 컨텍스트

벌크 수정연산과 벌크 삭제연산을 각각 수행한 후에 별도로 영속성 컨텍스트 초기화 작업을 하지 않았다고 가정하자. 이후에 전체조회 작업을 시행하면 update는 연산이 적용되지 않은 영속성 컨텍스트 데이터, delete는 연산이 적용된 DB 데이터 결과가 조회되는 것을 확인할 수 있다. 왜 그런 것일까? 이를 이해하기 위해선 영속성 컨텍스트를 제대로 이해하고 있어야 한다. 아래 예시와 함께 살펴보도록 하자. Update 벌크연산 상황 영속성 컨텍스트와 DB에 아래 데이터가 있다고 하자. 위 상황에서 아래와 같이 28살 미만은 이름을 전부 비회원으로 바꾸라는 bulk update 연산을 수행해보자. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Test public void bulkUpdate..

[JPA] 쓰기 지연으로 인한 쿼리 실행 시점과 예외처리 및 기본키 생성 전략

최근에 흥미로운 글을 봤다. JPA 쓰기지연 기능 때문에 커스터마이징한 예외가 발생하지 않고 DataIntegrityViolationException 예외가 발생한다는 글이었다. service에서 repository의 delete 메서드를 실행하고, 만약 외래키 설정으로 인한 DataIntegrityViolationException이 발생하면 catch로 잡아서 커스텀 예외를 던지려 하는 상황이라 가정하자. 해당 서비스 메서드를 테스트할 때, 예외 상황으로 커스텀 예외가 발생할 줄 알았는데 catch로 잡지 못하고 DataIntegrityViolationException가 발생했다는 글이었다. https://velog.io/@giantim/5 @Transactional 과 JPA 사용 시 주의점 @Tra..

[Infra] Spring + JPA 환경에 Flyway를 적용해보자

flyway는 DB 형상관리 오픈소스 툴이다. 즉, db schema가 변경이 발생할 때 flyway라는 툴로 관리를 할 수 있는 것이다. 이번 포스팅에서는 flyway 적용 방법에 대해 아주 간단히 알아볼 것이다. Flyway 사용 이유 배포 환경(prod)에서는 ddl-auto를 create, update, create-drop을 지양해야 한다. 배포된 db의 데이터들이 모두 증발될 수 있기 때문이다. 따라서, db schema 변경이 있을 때에 우리가 직접 배포 환경 db에 접속하여 schema를 작성해주어야 한다. 이는 매우 번거로우며 위험성 또한 높다. Flyway를 사용하면 이러한 번거로운 작업이 사라지게 된다. 변경된 스키마를 한눈에 확인할 수 있어 스키마 버전 관리에 용이해진다. flywa..

Infra/CI | CD 2022.08.08

[JPA] Spring Data JPA 페이징 기법을 적용해보자

조회 쿼리로 결과가 나올 때, 데이터가 너무 많으면 사용자가 보기에도 불편하고 로딩에도 오랜 시간이 걸린다. 그렇기 때문에 많은 사이트들에선 많은 데이터들을 페이지로 나누어서 관리한다. 스크롤을 내릴 때마다 데이터를 추가로 로드하는 무한 스크롤 방식을 사용하거나, 이전/다음 페이지로 이동하는 방식이 주로 사용된다. 이렇게 페이징 기법을 적용하려면 전체 데이터 개수와 요구되는 페이지넘버에 따른 인덱싱 계산을 해주어야 하는데, 실수할 여지도 많고 꽤나 번거롭다. 다행히 Spring Data JPA에서는 스스로 페이지 관련 인덱싱을 계산해준 결과를 반환해주는 기능을 제공해준다. 이번 포스팅에선 Spring Data JPA의 Pageable, Page에 대해 알아보고 MVC 패턴에서 Pageable이 어디까지 ..

반응형