Spring boot

2024.10.14 Blog 프로젝트 만들기(JPA) JPARepository 란?

정훈5 2024. 10. 14. 10:29

 

학습 목표 

Spring Data JPA에서 제공하는 JPARepository의 개념과 그 활용을 알아 보자.

 

 

JPARepository란?

Spring Data JPARepository 인터페이스를 통해 데이터 접근 계층을 간편하게 구현할 수 있도록 도와주는 프레임워크입니다. 개발자가 직접 DAO(Data Access Object) 클래스를 작성하지 않고도, JpaRepository를 상속받는 인터페이스에 메서드를 정의함으로써 데이터베이스와의 상호작용을 처리할 수 있습니다.

 

 

주요 메서드 확인

  • save(S entity): 엔티티를 저장하거나 업데이트합니다.
  • findById(ID id): ID로 엔티티를 조회합니다.
  • findAll(): 모든 엔티티를 조회합니다.
  • deleteById(ID id): ID로 엔티티를 삭제합니다.
  • count(): 엔티티의 개수를 반환합니다.
  • existsById(ID id): 특정 ID의 엔티티 존재 여부를 확인합니다.

 

커스텀 쿼리란?

JPARepository가 기본적으로 제공하지 않는 특정 요구사항을 만족시키기 위해 작성하는 사용자 정의 쿼리를 의미합니다. 이는 다음과 같은 방법으로 작성할 수 있습니다:

 

 

주요 작성 방법

  • 메서드 이름 기반 쿼리 메서드(Query Methods)
  • @Query 어노테이션을 사용JPQL 또는 네이티브 쿼리
  • Querydsl을 사용한 동적 쿼리

 

쿼리 메서드(Query Methods)

// 특정 이메일을 가진 사용자 조회
Optional<User> findByEmail(String email);

// 나이가 특정 값 이상인 사용자 목록 조회
List<User> findByAgeGreaterThan(Integer age);

// 사용자 이름을 기준으로 내림차순 정렬된 사용자 목록 조회
List<User> findAllByOrderByUsernameDesc();

 

JPQL 사용 예시

@Query("SELECT u FROM User u WHERE u.username LIKE %:keyword%")
List<User> searchUsersByUsername(@Param("keyword") String keyword);

 

Native Query 사용 예시

@Query(value = "SELECT * FROM user_tb u WHERE u.username LIKE %:keyword%", nativeQuery = true)
List<User> searchUsersByUsernameNative(@Param("keyword") String keyword);

 

Querydsl 사용 예시

QuerydslJava 메서드를 사용하여 엔티티(Entity) 기반으로 타입 안전한 쿼리를 생성하는 프레임워크이다.

// Querydsl을 동적 쿼리

QUser user = QUser.user;
List<User> users = queryFactory.selectFrom(user)
    .where(user.username.eq("john").and(user.age.gt(25)))
    .fetch();
------------------------------------------------------    
// Querydsl을 사용하여 조건에 따라 동적으로 필터링

BooleanBuilder builder = new BooleanBuilder();
if (username != null) {
    builder.and(user.username.eq(username));
}
if (age != null) {
    builder.and(user.age.gt(age));
}
List<User> users = queryFactory.selectFrom(user)
    .where(builder)
    .fetch();

 

커스텀 쿼리의 방법별 특징

  1. 메서드 이름 기반 쿼리 메서드(Query Methods)
    • 자동 생성: 메서드 이름에 따라 자동으로 JPQL 쿼리를 생성합니다.
    • 간편성: 간단한 조회 작업에 적합하며, 코드가 간결합니다.
    • 한계: 복잡한 조건이나 다중 조인이 필요한 경우에는 한계가 있습니다.
  2. @Query 어노테이션을 사용한 커스텀 쿼리
    • JPQL 쿼리: 엔티티를 대상으로 객체 지향적으로 쿼리를 작성할 수 있습니다.
    • 네이티브 쿼리: 실제 SQL을 사용하여 데이터베이스 특정 기능을 활용하거나, 성능을 최적화할 수 있습니다.
    • 유연성: 복잡한 쿼리나 특정 요구사항을 충족시킬 수 있습니다.

 

 

 

BoardJPARepository.java

더보기
package com.tenco.blog_v1.board;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.Optional;

// @Repository 생략가능
public interface BoardJPARepository extends JpaRepository<Board, Integer>{

    // 커스텀 쿼리 만들어 보기
    // Board 와 User 엔티티를 조인하여 특정 Board 엔티티를 조회한다.
    @Query("select b from Board b join fetch b.user u where b.id = :id")
    Optional<Board> findByIdJoinUser(@Param("id") int id);
    
}

 

UserJPARepository.java

더보기
package com.tenco.blog_v1.user;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;

import java.util.Optional;

public interface UserJPARepository extends JpaRepository<User, Integer> {

    // 사용자 이름과 비밀번호를 조회하는 메서드 이름 기반 쿼리를 작성
    Optional<User> findByUsernameAndPassword(@Param("username") String username,
                                             @Param("password") String password);

    // 사용자 이름
    // 메서드 이름 기반
    Optional<User> findByUsername(@Param("username") String username);

}

패키지 이름은 user

 

UserJPARepositoryTest.java

더보기
package com.tenco.blog_v1.user;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.Optional;

/**
 * 패키지명이 동일 해야 한다.
 * UserJPARepository 기능을 테스트 하는 클래스 입니다.
 *
 * DataJpaTest : 어노테이션은 JPA 관련 컴포넌트를 로드하여 테스트 환경을 만들어 준다.
 */

@DataJpaTest
public class UserJPARepositoryTest {

    @Autowired
    private UserJPARepository userJPARepository;

    @Test
    @DisplayName("사용자 이름으로 조회하는 테스트")
    public void findByUsername_test() {

        // given - 테스트에 필요한 초기 조건 설정
        String username = "카리나";

        // when - 테스트 대상 메서드 실행
        Optional<User> userOpt = userJPARepository.findByUsername(username);

        // eye ~
        System.out.println(username);
        System.out.println(userOpt.toString());

        // then

    }

}