본문 바로가기

Java/JPA

SpringDataJPA - 메서드 및 유연한 반환타입

SpringDataJPA 주요 메서드


save(S) : 새로운 엔티티는 저장하고 이미 있는 엔티티는 병합한다.
delete(T) : 엔티티 하나를 삭제한다. 내부에서 EntityManager.remove() 호출
findById(ID) : 엔티티 하나를 조회한다. 내부에서 EntityManager.find() 호출
getOne(ID) : 엔티티를 프록시로 조회한다. 내부에서 EntityManager.getReference() 호출
findAll(…) : 모든 엔티티를 조회한다. 정렬( Sort )이나 페이징( Pageable ) 조건을 파라미터로 제공할 수 있다.


참고: JpaRepository 는 대부분의 공통 메서드를 제공한다.


쿼리메소드 기능

쿼리 메소드 기능 3가지

- 메소드 이름으로 쿼리 생성(간단한 쿼리 사용 시)
- 메소드 이름으로 JPA NamedQuery 호출 (실무에서 거의 사용 안함)
- @Query 어노테이션을 사용해서 리파지토리 인터페이스에 쿼리 직접 정의(조금 복잡한 쿼리 사용 시)

*동적쿼리는 QueryDSL 사용(깔끔하고 유지보수성 좋음)

 

공식문서 참고

https://docs.spring.io/spring-data/jpa/reference/jpa/query-methods.html

 

JPA Query Methods :: Spring Data JPA

As of Spring Data JPA release 1.4, we support the usage of restricted SpEL template expressions in manually defined queries that are defined with @Query. Upon the query being run, these expressions are evaluated against a predefined set of variables. Sprin

docs.spring.io

 

스프링 데이터 JPA가 제공하는 쿼리 메소드 기능(메서드 이름으로 쿼리 생성)

짧은 쿼리들 작성 시 사용(복잡한 쿼리는 이렇게 사용할 수 없음. 2가지 조건 넘어가면 다른 방법 사용해야함)

 

조회: find…By ,read…By ,query…By get…By, 
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.querymethods.query-creation
예:) findHelloBy 처럼 ...에 식별하기 위한 내용(설명)이 들어가도 된다.
COUNT: count…By 반환타입 long
EXISTS: exists…By 반환타입 boolean
삭제: delete…By, remove…By 반환타입 long
DISTINCT: findDistinct, findMemberDistinctBy
LIMIT: findFirst3, findFirst, findTop, findTop3

 

@Query 어노테이션을 사용해서 리파지토리 인터페이스에 쿼리 직접 정의

실무에서 많이 사용하는 기능

JPQL을 바로 작성할 수 있다.

public interface MemberRepository extends JpaRepository<Member, Long> {
    
    @Query("select m from Member m where m.username = :username and m.age = :age")
    List<Member> findUser(@Param("username") String username, @Param("age") int age);

 

@Query 로 단순한 값, DTO 조회하기

 

1. 값타입으로 조회하기


@Query("select m.username from Member m")
List<String> findUsernameList(); // username 타입이 String

 

2.DTO로 조회하기 (Dto 생성자와 매칭해야 한다)

 

예시에서는 team엔티티와 조인해서 조회하였음.

// Dto 조회시 new Operation 작성 필수(생성자와 매칭)
@Query("select new study.datajpa.dto.MemberDto(m.id, m.username, t.name) from Member m join m.team t")
List<MemberDto> findMemberDto();

 

실제 실행 쿼리 :

 

select m1_0.member_id,m1_0.username,t1_0.name from member m1_0 join team t1_0 on t1_0.team_id=m1_0.team_id

 

* 컬렉션 파라미터 바인딩(IN절 사용)

실무에서 많이 사용

컬렉션과 IN절을 사용해서 조회하는 방법이다

// 컬렉션과 IN절 이용해서 조회
@Query("select m from Member m where m.username in :names")
List<Member> findByNames(@Param("names") Collection<String> names);
@Test // 컬렉션 IN절 사용한 쿼리
public void findByNames() throws Exception {
    // given
    Member m1 = new Member("AAA",10);
    Member m2 = new Member("BBB",20);
    memberRepository.save(m1);
    memberRepository.save(m2);

    List<Member> result = memberRepository.findByNames(Arrays.asList("AAA", "BBB"));
    for (Member member : result) {
        System.out.println("member = " + member);
    }

}

 


반환타입의 유연성

 

반환타입의 유연성 : Spring Data JPA가 반환타입을 유연하게 지원해준다.

public interface MemberRepository extends JpaRepository<Member, Long> {


    // Spring Data JPA가 반환타입을 유연하게 지원해줌.
    List<Member> findListByUsername(String username); // 컬렉션
    Member findMemberByUsername(String username); // 단건
    Optional<Member> findOptionalByUsername(String username); // 단건 Optional

 

 

주의할 점

 

1.List로 반환하는 경우 DB에 일치하는 데이터가 없을때, List가 null이 아니라 비어있는 List를 반환한다.


@Test
public void returnType() throws Exception {
    // given
    Member m1 = new Member("AAA", 10);
    Member m2 = new Member("BBB", 20);
    memberRepository.save(m1);
    memberRepository.save(m2);

    List<Member> aaa = memberRepository.findListByUsername("dasfadf");
    System.out.println("aaa = " + aaa.size());

}

출력값 : aaa = 0

 

2. 단 건으로 조회하는 경우 결과값이 없으면 null을 반환한다(JPA와 달리 Exception이 발생하지 않음)

Member findMember = memberRepository.findMemberByUsername("dasfadf");
System.out.println("findMember = " + findMember);

출력값 : findMember = null

 

DB조회 시 null인지 아닌지 모를때는 Optional을 활용하자

 

'Java > JPA' 카테고리의 다른 글

SpringDataJPA - 벌크성 수정 쿼리  (0) 2024.01.10
SpringDataJPA - 페이징을 쉽게 하는 법  (0) 2024.01.10
JPA실전 2 - OSIV와 성능  (0) 2023.12.12
JPA 실전2편 - 주문조회 API  (0) 2023.12.12
JPA 실전2편 - 회원 관련 API  (0) 2023.12.07