Spring/JPA

    Querydsl Projection - with 1:N DTO 매핑 (프로젝션)

    querydsl docs 프로젝션 프로젝션이란 "Select절에 조회 대상을 지정"하는 것이다 조회대상이 하나라면 Return Type은 해당 조회 대상의 Type으로 정해진다 조회대상이 여러개라면 QueryDSL에서는 프로젝션 대상으로 여러 필드를 선택하게 되면 Tuple이라는 "Map과 비슷한" Type을 return해준다 쿼리에 대한 결과를 엔티티가 아닌 "특정 객체(DTO..)"로 받고 싶다면 Bean Population을 사용한다 QueryDsl Projections 을 사용해서 1:N 관계의 List 를 추출하는 코드 부모 DTO @Getter @Setter @AllArgsConstructor @NoArgsConstructor public class ParentDto { private UUID..

    QueryDSL 에러 - Execution failed for task ':compileQuerydsl', ClassNotFoundException: org.gradle.wrapper.GradleWrapperMain

    테스트코드 에러 - Execution failed for task ':compileQuerydsl'. Task :compileQuerydsl FAILED error: cannot find symbol Execution failed for task ':compileQuerydsl'. 같은 에러 발생시에는 Preference -> Build.Execution, Deployment -> Build Tools -> gradle build and run using : Intellij IDEA Run tests using : Intellij IDEA 로 설정하고 다시 테스트하면 테스트가 통과한다. 오류: 기본 클래스 org.gradle.wrapper.GradleWrapperMain을(를) 찾거나 로드할 수 없습니다..

    QueryDSL 설정 - SpringBoot 2.7.X & SpringBoot 3.x 버전

    SpringBoot 2.x대와 SpringBoot 3.x대의 버전 설정 방법이 다르므로 둘에 나눠서 정리 하도록 한다. SpringBoot 2.x버전대 설정 방법 1. Querydsl 버전을 plugins 위에 추가하고 plugins에 querydsl 플러그인을 추가한다. buildscript { ext { queryDslVersion = "5.0.0" } } plugins { id 'java' id 'org.springframework.boot' version '2.7.7' id 'io.spring.dependency-management' version '1.1.0' id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" // querydsl } builds..

    Jpa Insert, update delete 시 select query를 통한 먼저 조회하지 않는 방법.md

    Spring Data Jpa에서는 대부분 JpaRepository interface를 상속받는데, 이 때 기본 구현체로 SimpleJpaRepository.class가 사용된다. 다음은 SimpleJpaRepository의 save method 코드이다. @Transactional @Override public S save(S entity) { Assert.notNull(entity, "Entity must not be null."); if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else { return em.merge(entity); } } } JpaRepository.save 동작방식은 persist 하거나 m..

    Jpa Id 생성전략에 따른 동작 방식

    JpaRepository.save 동작방식은 persist 하거나 merge를 한다. @Transactional @Override public S save(S entity) { Assert.notNull(entity, "Entity must not be null."); if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else { return em.merge(entity); } } } 엔티티에 Id 값이 있으면 DB를 조회 (select)한 후에 insert 하게 된다. 생성전략이 존재하지 않을 경우 merge 로 동작. merge 는 입력받은 entity 를 복사한 후 진행하기에 리소스 소모가 있다. 생성전략이 존재하..

    JPA Hibernate Id 생성 전략과 UUID 전략

    JPA 및 Hibernate 내에서 엔티티에 대한 식별자(Id)를 생성하는 다양한 옵션에 대해 정리한다. 식별자는 엔티티 기본 키를 모델링하고 특정 엔터티를 고유하게 식별하는 데 사용된다. 기본 키는 데이터베이스 내의 행을 고유하게 식별한다. 이론적으로 식별자는 기본 키와 일치할 필요가 없다. 식별자는 각 행을 고유하게 식별하는 열에 매핑되기만 하면 되기 때문이다. 여기서는 기본 키와 식별자(Id) 는 일부로 같은 의미로 사용한다. 기본키와(pk) 식별자(Id)는 다음 제약조건이 제한된다 UNIQUE- 값은 각 행을 고유하게 식별해야 한다. NOT NULL- 값은 null일 수 없다. 복합 ID (복합 키)의 경우 어떤 부분도 null이 될 수 없다. IMMUTABLE- 한 번 삽입된 값은 절대 변경할 ..

    Jpa Hibernate Custom Id Generator

    custom ID를 생성하기 위해 Custom Generator 를 생성하기 위해서는 IdentifierGenerator 인터페이스를 이용해서 generate() 메서드를 구현해야 한다. IdentifierGenerator 인터페이스구현 클래스는 반드시 public 으로 선언된 기본 생성자가 있어야한다 package org.hibernate.id; public interface IdentifierGenerator extends Configurable, ExportableProducer { ... Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException; } Identifier..

    Jpa ArrayType. PostgreSQL Array Type을 저장하는 방법 - Hibernate Types, List, Array

    PostgreSQL을 포함한 몇몇 RDB에서는 Array Type의 컬럼 유형을 지원한다. 그러나 hibernate에서 제공해주는 기본 Type들은 Array Type을 지원하지 않는다. 개발자는 Hibernate Type을 Custom 구현해서 사용하거나, 라이브러를 이용해서 PostgreSQL ArrayType을 Spring-data-jpa를 이용해서 hibernate로 매핑할 수 있다. 테스트에 사용된 도메인 엔티티는 다음과 같다. 도메인 엔티티 @Entity public class User { @Id private Long id; private String name; private String[] roles; private List hobbies; } 1. Custom Hibernate Type ..

    Cannot call sendError() after the response has been committed - 순환 참조 문제 With JPA Entity

    Cannot call sendError() after the response has been committed - 순환 참조 문제 이 문제는 Jackson을 이용한 직렬화/ 역직렬화 과정에서 발생한다. 일반적으로 JPA Entity에서 양방향 관계를 맺었을 떄, 컨트롤러의 API 응답결과로 Entity를 반환하면 Jackson은 응답 결과 객체의 필드를 바탕으로 JSON을 만든다. 이 때 양방향 관계로 서로를 참조하고 있으니 무한하게 재귀적으로 참조를 하다가 StackOverFlow가 발생하여 직렬화를 못하고 에러를 발생시키는 문제이다. 응답이 커밋된 후 sendError()를 호출할 수 없다. Infinite Recursion - 무한 재귀 원인 먼저 Jackson 무한 재귀 문제 원인을 살펴보자 간단..

    Jpa 쿼리 파라미터 로그 확인방법 - With DataJpaTest p6spy

    Spring Boot 기본 설정으로는 hibernate SQL 바인딩 변수 자리에 '?' 표시된 SQL 과 바인딩 변수 값이 따로 표시되어 SQL 디버깅이 불편하다. 쿼리 파라미터가 어떤 값을 가지고 있는지 확인할 수 있는 2가지 방법과 커스텀 방법에 대해 정리한다. 일반적으로 2번째 방법인 p6spy가 더 자세하고 편리하게 사용할 수 있지만, 리소스를 많이 사용하니 운영 환경에서는 사용하지 않는게 좋아 보인다. JPA 쿼리 파라미터 로그 체크 설정 파일을 통한 로그 설정 yaml 또는 properties 파일을 통한 로그 레벨 설정으로 쿼리 파라미터 바인딩을 확인할 수 있다. yaml logging: level: org.hibernate.SQL: debug org.hibernate.type.descri..