[JPA] JPA와 Query Method

keymu·2024년 12월 26일
0

1. JPA

Persistence:

  • 영속성
  • 데이터를 생성한 프로그램이 종료되어도 사라지지 않는 데이터의 특성
  • 영구적으로 파일, 데이터베이스 등 활용하여 저장

ORM:

  • object relational mapping
  • 비영속성 객체를 영속성 객체에 연결해주는 기술
  • 직접 매핑하기 때문에 쿼리문을 거의 다루지 않음
  • 자바 객체 다루듯 작업

JPA:

  • Java Persistence API
  • Java 진영에서 ORM 표준으로 채택된 API
  • 데이터베이스 코드 관련 유연성
  • 어설프게 다루면 성능 이슈 만들 수 있음
  • 데이터베이스에 대해 독립적이라, 특정 데이터베이스의 강력한 기능 활영하기 어려움

Hibernate:

  • JPA의 실제 구현체

Spring Data JPA:

  • Hibernate를 더 간편하게 사용하기 위해 만든 기술

이제까지 사용한 MyBatis -> Persistence Context

Entity:

Entity Manager:

  • persistenece context에 넣어두고 객체들의 생사 관리
  • 엔티티에 대한 정보를 수정한다

엔티티 Manager 메소드의 상태

  • 비영속 상태
  • 영속된
  • Detached(준영속)
  • 지워져야 함

Optional:

  • null일 수도 있는 객체를 감싸는 래퍼 클래스
  • NullPointerException을 방지하는데 도움을 줌
  • 명시적으로 값이 없을 수 있다는 것을 표현

Optional 사용 시 주의사항:

  • Optional을 필드로 사용하지 않기
  • Optional을 생성자나 메서드의 매개변수로 사용하지 않기
  • Collections, Arrays 등의 컨테이너를 Optional로 감싸지 않기
  • Optional.get() 직접 호출은 피하고 대신 orElse, orElseGet, orElseThrow
// Optional 생성
Optional<String> opt1 = Optional.empty();  // 빈 Optional
Optional<String> opt2 = Optional.of("값");  // null이 아닌 값으로 Optional 생성
Optional<String> opt3 = Optional.ofNullable(nullable);  // null일 수도 있는 값으로 생성

// 값 처리
opt.isPresent();  // 값이 존재하는지 확인
opt.isEmpty();    // 값이 없는지 확인
opt.get();        // 값 가져오기 (값이 없으면 예외 발생)
opt.orElse("기본값");  // 값이 없을 때 기본값 반환
opt.orElseGet(() -> "기본값 생성");  // 값이 없을 때 기본값 생성
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
}

@Service
public class UserService {
    public User getUser(String email) {
        return userRepository.findByEmail(email)
            .orElseThrow(() -> new UserNotFoundException("사용자를 찾을 수 없습니다"));
    }
}

Flush:

  • SQL쿼리의 변화를 주는게 아니라 'DB 반영 시점'을 조정한다.
  • 로그 출력으로는 변화를 확인하기 힘들다

QueryByExample(QBE)

  • 복잡한 조건에 대한 쿼리문을 작성할 때 사용
  • 비교적 최근에 만들어짐
  • 크게 효과적이진 않음

2. Query Method

  • where 조건절을 메소드 이름 선언만으로 만들어주도록 한다
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByName(String name);
    User findByEmail(String email);
}
  • Repository 인터페이스를 생성하고 JpaRepository를 상속받는다.
  • 제네릭 타입으로 엔티티 클래스와 ID 타입을 지정한다.
  • 메소드 이름 규칙에 따라 쿼리 메소드를 정의.
User findByEmail(String email);
User getByEmail(String email);
User readByEmail(String email);
User queryByEmail(String email);
User searchByEmail(String email);
User streamByEmail(String email);

조건절 키워드

비교 연산자

List<User> findByAgeGreaterThan(int age);              // > 
List<User> findByAgeGreaterThanEqual(int age);         // >=
List<User> findByAgeLessThan(int age);                 // 
List<User> findByAgeLessThanEqual(int age);            // <=

논리 연산자

List<User> findByEmailAndName(String email, String name);   // AND
List<User> findByEmailOrName(String email, String name);    // OR 

Between

List<User> findByCreatedAtBetween(LocalDateTime start, LocalDateTime end);
List<User> findByAgeBetween(int start, int end);

Like 검색

List<User> findByNameStartingWith(String prefix);      // LIKE 'prefix%'
List<User> findByNameEndingWith(String suffix);        // LIKE '%suffix'
List<User> findByNameContains(String word);           // LIKE '%word%'
List<User> findByNameLike(String likePattern);        // 

LIKE 직접 지정, NULL 체크, IN 절

List<User> findByIdIsNotNull();
List<User> findByIdIsNull();
List<User> findByNameIn(List<String> names);

정렬과 페이징

// 메소드 이름으로 정렬
List<User> findByNameOrderByIdDesc(String name);

// Sort 파라미터로 정렬
List<User> findByName(String name, Sort sort);

페이징

// Pageable 파라미터로 페이징 처리
Page<User> findByName(String name, Pageable pageable);

// 사용 예시
PageRequest pageRequest = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "id"));
Page<User> userPage = userRepository.findByName("John", pageRequest);

예시

// 최근 24시간 내 생성된 활성 사용자 찾기
List<User> findByCreatedAtAfterAndActiveTrue(LocalDateTime yesterday);

// 특정 이메일 도메인을 사용하는 사용자 찾기
List<User> findByEmailEndingWith(String domain);

// 이름으로 검색하고 ID로 정렬하여 상위 5명 가져오기
List<User> findTop5ByNameContainingOrderByIdDesc(String name);
profile
Junior Backend Developer

0개의 댓글