Spring/SpringDataJPA 23

네이티브 쿼리

JPA가 SQL query를 그대로 사용하는 네이티브 쿼리를 지원한다. 하지만 가급적 네이티브 쿼리는 사용하지 않는게 좋다. 최근에 나온 final 방법 => 스프링 데이터 Projections 활용 스프링 데이터 JPA 기반 네이티브 쿼리 페이징 지원 반환 타입 Object[] Tuple DTO(스프링 데이터 인터페이스 Projections 지원) 제약이 있는데 Sort 파라미터를 통한 정렬이 정상 동작하지 않을 수 있고 JPQL처럼 Application loading 시점에 문법 확인이 불가하고 동적 쿼리가 불가능하다. // MemberRepository Interface @Query(value = "select * from member where username = ?", nativeQuery = ..

Projections

DB에서 엔티티를 조회하고 싶을 때도 있지만 회원의 이름만 조회하고 싶을때가 있다. JPA를 통해서 조회를 하게되면 엔티티를 통채로 조회하게 되면 쿼리의 데이터가 엄청 커지게 된다. 이름만 조회를 하고 싶을때 편하게 하는 방법을 Projections라고 한다. 쿼리에 SELECT절에 들어갈 데이터라고 보면 된다. UsernameOnly Interface를 만들고 package study.datajpa.repository; public interface UsernameOnly { String getUsername(); } MemberRepository Interface에 아래구문을 추가해준다. // 엔티티가 아니라 인터페이스 UsernameOnly에 구현체 프록시 객체가 담겨서 간다. List findPr..

Specifications(명세)

Specifications Query By Example Projections 네이티브 쿼리 Specifications을 지원하는데 JPA Criteria를 활용해서 개념을 사용할 수 있도록 지원해준다. => 실무에서 잘 사용하지 않는다. 술어(predicate) 참 또는 거짓으로 평가 AND OR 같은 연산자로 조합해서 다양한 검색조건을 쉽게 생성(디자인 패턴을 컴포지트 패턴으로 생성) 예) 검색 조건 하나하나 스프링 데이터 JPA는 `org.springframework.data.jap.domain.Specification` 클래스로 정의 사용방법을 보고 간단하게 넘어가자. // MemberRepository Interface public interface MemberRepository extends ..

새로운 엔티티를 구별하는 방법

새로운 엔티티를 판단하는 기본 전략 식별자가 객체일 때 `null`로 판단 식별자가 자바 기본 타입일 때 `0`으로 판단 `Persistable` 인터페이스를 구현해서 판단 로직 변경이 가능 Item Class를 하나 만들고 // Item Class package study.datajpa.entity; import lombok.Getter; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity @Getter public class Item { @Id @GeneratedValue private Long id; } ItemRepository Interface도 만들..

스프링 데이터 JPA 구현체 분석

스프링 데이터 JPA가 제공해는 공통 인터페이스의 구현체가 존재한다. 아래의 경로로 들어가보자 아래의 SimpleJpaRepository가 JPA의 구현체이다. 그리고 SimpleJpaRepository는 Repository가 이미 걸려있는데 두가지 의미가 있다. Spring Bean의 컴포넌트 스캔 대상이 되는 것 => 스프링이 읽어들여서 컨테이너에 올리게 되는 것이고 두번째는 JPA나 JDBC 둘 다 exception이 틀리기 때문에 이게 터지면 영속성 계층에 있는 것들을 Spring에서 쓸 수 있는 예외들로 다 바꿔준다. 서비스 계층이나 컨트롤러 계층에 있는 것들을 넘길 때 JPA exception이나 JDBC exception이 올라가는 것이 아니고 Spring Framework이 제공하는 exc..

Web 확장 - 도메인 클래스 컨버터 & 페이징과 정렬

path variable 기반으로 코드를 작성해보자. // MemberController Class package study.datajpa.controller; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import study.datajpa.entity.Member; import study.datajpa.repository.MemberRepository; ..

사용자 정의 리포지토리 구현

스프링 데이터 JPA 리포지토리는 인터페이스가 구현만 되어있고 모두 상속을 받아야 하기 때문에 현실적이지 않다. 스프링 데이터 JPA가 아니라 JDBC를 직접 활용을 해서 기능을 쓴다거나 MyBatis library 기능을 쓴다거나 완전히 다른 Repository 기능을 쓰고 싶을 때 이런걸 쓸 수 있게 열어놓은 것이 사용자 정의 리포지토리 구현이다. 다양한 이유로 인터페이스의 메서드를 직접 구현하고 싶으면 JPA 직접 사용( EntityManager ) 스프링 JDBC Template 사용 MyBatis 사용 데이터베이스 커넥션 직접 사용 등등... Querydsl 사용하면 된다. 그리고 여러 커스텀 기능을 스프링 데이터 JPA가 제공해주는 것을 알고 코드를 작성해보자. // MemberReposito..

JPA Hint & Lock

JPA 쿼리 힌트 (SQL 힌트가 아니라 JPA 구현체에게 제공하는 힌트)이고 코드로 살펴보면 Hibernate는 readOnly라는 쿼리기능을 제공한다. JPA 영속성 컨텍스트에 딱 넣어놓고 (transaction commit 할때 자동으로 commit가 되는데 ) 강제로 flush를 하면 실제 db에 insert 쿼리가 나가고(영속성 컨텍스트에 member가 남아있는 상태로 => JPA 영속성 컨텍스트 안에 1차 캐시가 있는데 그걸 지우는 건 아니고 그것의 결과를 db에 동기화를 하는 것이고) clear를 하면 영속성 컨텍스트가 다 날라간다. 그 이후로 JPA에서 조회를 하면 영속성 컨텍스트에 1차캐시가 없기 때문에 db를 무조건 조회한다. // MemberRepositoryTest @Test pub..

@EntityGraph

JPA의 fetchjoin 기술(지연로딩개념 : LAZY)을 명확히 이해한 다음에 @EntityGraph로 넘어오자. 먼저 MemberRepositoryTest를 작성하면 member1은 teamA를 참조하고 member2는 teamB를 참조한다. @Test public void findMemberLazy() { //given //member1 -> teamA //member2 -> teamB Team teamA = new Team("teamA"); Team teamB = new Team("teamB"); teamRepository.save(teamA); teamRepository.save(teamB); Member member1 = new Member("member1", 10, teamA); Membe..