반응형

JPA 21

[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이 어디까지 ..

[JPA] Spring Data JPA로 생성일자, 수정일자 컬럼을 간단히 추가하자

Spring Data JPA에는 Auditing 기능을 편하게 다룰 수 있도록 @CreatedDate, @LastModifiedDate 어노테이션을 제공해준다. 그리고 생성일자, 수정일자 컬럼은 웬만한 모든 도메인에 있으면 로깅 및 사용자 입장에서도 간편하다. 따라서 보통 BaseEntity라는 생성일자, 수정일자가 들어있는 상위 엔티티를 만들고 상속 구조를 이용하는 방법을 진행한다. 이번 포스팅에서는 이 방법에 대해 기록해보려 한다. 개발환경 Spring Boot 2 버전 Spring Data JPA lombok 프로덕션 코드 BaseEntity @EntityListeners(AuditingEntityListener.class) @MappedSuperclass @Getter abstract public..

[JPA] 양방향 연관관계에서 JPA 내부 작동 원리_영속성 컨텍스트의 이해

JPA 작동 원리를 이해하지 못해 영속성 컨텍스트의 흐름을 알지 못할 경우 발생할 수 있는 문제이다. 블로그에 따로 포스팅이 돼있지 않아서 JPA 스터디를 하는 겸 기록해보려고 한다. 들어가기 전에 스프링 환경에서 JPA ORM을 이용하고 있다. Member : Team이 N:1 양방향 연관관계를 가지고 있다. 'wooteco' 팀에 'kth990303'을 넣으려고 하는 예제를 이용할 것이다. 결론부터 말하자면? JPA의 내부 작동 흐름에 대해 이해하는 것이 정말 중요하다. (영속성 컨텍스트의 흐름에 대한 이해가 부족하면 문제 발생 확률이 높아지고, 문제 원인도 못찾을 수 있다.) 양방향 연관관계에서는 객체의 값을 INSERT할 때, 안전하게 두 객체 모두에게 반영해주자. 두 객체의 메서드를 사용하거나,..

반응형