[SpringBoot] JPA Repository

김선형·2025년 9월 11일

Java

목록 보기
25/27

개요

Spring Data JPA가 제공하는 인터페이스로, JPA를 더 쉽게 다루기 위한 추상화 계층이다. 개발자가 데이터베이스에 접근하는 코드 DAO를 직접 구현하지 않고도 데이터베이스를 조작할 수 있도록 하는 인터페이스 기반 프레임워크이다.

주요 메서드

조회

메서드 시그니처설명
Optional<T> findById(ID id)PK로 엔티티 단건 조회
List<T> findAll()모든 엔티티 조회
List<T> findAllById(Iterable<ID> ids)여러 PK로 엔티티 조회
<S extends T> List<S> findAll(Example<S> example)Example 조건에 맞는 전체 엔티티 조회
<S extends T> Optional<S> findOne(Example<S> example)Example 조건에 맞는 엔티티 1개 조회
long count()전체 엔티티 개수 반환
<S extends T> long count(Example<S> example)Example 조건에 맞는 엔티티 개수 반환
boolean existsById(ID id)해당 PK 엔티티 존재 여부
<S extends T> boolean exists(Example<S> example)Example 조건에 맞는 엔티티 존재 여부
T getReferenceById(ID id)프록시 엔티티 반환 (JPA Lazy Loading)

저장 및 수정

메서드 시그니처설명
<S extends T> S save(S entity)엔티티 저장 또는 병합 (수정)
<S extends T> List<S> saveAll(Iterable<S> entities)여러 엔티티 저장/수정
<S extends T> S saveAndFlush(S entity)엔티티 저장/수정 후 즉시 flush
void flush()영속성 컨텍스트 변경 내용을 DB에 즉시 반영

✏️ flush()?
JPA에서 영속성 컨텍스트의 변경 내용을 즉시 DB에 반영하도록 하는 메서드다. JPA는 기본적으로 트랜잭션이 commit되는 시점에 자동으로 flush를 호출하여 DB에 쿼리를 실행한다.
대표적으로, DB에 즉시 쿼리를 반영해야 할때, 트랜잭션 내에서 쿼리 동작 순서를 명확히 해야 할 때, JPA 이벤트 리스너나 복잡한 이벤트 처리 로직을 실행할 때 flush()를 직접 호출한다.

삭제

메서드 시그니처설명
void deleteById(ID id)PK 기준 엔티티 삭제
void delete(T entity)엔티티 단건 삭제
void deleteAllById(Iterable<? extends ID> ids)여러 PK 엔티티 삭제
void deleteAll(Iterable<? extends T> entities)여러 엔티티 삭제
void deleteAll()모든 엔티티 삭제
void deleteAllInBatch()모든 엔티티 일괄 (벌크) 삭제
void deleteAllInBatch(Iterable<T> entities)전달받은 엔티티만 일괄 (벌크) 삭제
void deleteAllByIdInBatch(Iterable<ID> ids)여러 PK 엔티티만 일괄 (벌크) 삭제

페이징 및 정렬

메서드 시그니처설명
List<T> findAll(Sort sort)정렬 조건에 맞게 전체 엔티티 조회
Page<T> findAll(Pageable pageable)페이징 조건에 맞는 엔티티 페이지 조회
<S extends T> List<S> findAll(Example<S> example, Sort sort)Example + Sort 조건으로 엔티티 조회

사용자 정의 메서드

JPA Repository 기본 제공 메서드나 간단한 쿼리 메서드만으로 해결하기 어려운 복잡한 조회 조건 또는 특정 데이터 형태의 조회가 필요할 때 작성한다.
여러 테이블을 조인할 때, 특정 조건에 따라 동적으로 쿼리를 만들어야 할 때, 전체 엔터티가 아닌 일부 데이터만 DTO 형태로 가져와 성능을 개선하고 싶을 때 필요하다.

생성 방법

쿼리 메서드

메서드 명 규칙만으로 자동 쿼리를 생성한다.
쉽고 빠르며, 실수를 방지할 수 있다. 단순 조건, 검색, 정렬에 매우 효율적이다. 반면 조인, 복잡 논리, 그룹/집계, 복잡 동적 쿼리에는 적합하지 않다.

쿼리 메서드 키워드

구분키워드(메서드 내 단어)의미 / 동작예시 메서드명
조회find, read, get, query, search,
stream, count, exists, delete,
remove
조회, 개수, 존재 여부, 삭제, etc.findByName, countByAge,
existsByEmail
조건By뒤에 오는 조건 필드 지정findByName, findByAge
And, Or조건 연결 (AND/OR)findByNameAndAge,
findByNameOrEmail
Is, Equals같음 (=)findByNameIs,
findByNameEquals
Between범위 (사이)findByAgeBetween
LessThan, Before미만 (<)findByAgeLessThan
GreaterThan, After초과 (>)findByAgeGreaterThan
LessThanEqual이하 (<=)findByAgeLessThanEqual
GreaterThanEqual이상 (>=)findByAgeGreaterThanEqual
IsNull, IsNotNullNull/Null이 아님findByEmailIsNull,
findByEmailIsNotNull
In, NotIn컬렉션 내 포함/불포함findByStatusIn,
findByAgeNotIn
StartingWith문자열로 시작하는
(Like 'xxx%')
findByNameStartingWith
EndingWith문자열로 끝나는
(Like '%xxx')
findByNameEndingWith
Containing, Contains포함 (Like '%xxx%')findByNameContaining
Like, NotLikeLike, Not LikefindByNameLike,
findByNameNotLike
True, False불리언 값findByActiveTrue
정렬OrderBy정렬 조건findByNameOrderByAgeDesc
페이징Pageable, Slice페이징 파라미터 사용findByName(String name,
Pageable pageable)

@Query (JPQL)

JPQL (엔터티 기반)로 커스텀 쿼리를 작성한다.
복잡 조건, 조인, 집계, 부분 컬럼 추출 등에 적합하나, 동적 조건이 많으면 코드가 지저분해지고 컴파일러 타입 체크가 어렵다.

@Query("select u from User u where u.status = :status and u.age >= :minAge")
List<User> findActiveUsers(@Param("status") UserStatus status, @Param("minAge") int minAge);

@Query (Native)

실제 DB SQL로 쿼리를 작성한다.
DB에 최적화되어 있으며, 고급 쿼리 작성이 가능하다. 그러나 DB 종속적이고 유지보수가 어렵다.

@Query("SELECT * FROM users WHERE status = ?1 AND created_at > ?2", nativeQuery = true)
List<User> findActiveUsersNative(String status, LocalDateTime createdAt);

QueryDSL

Java 코드를 기반으로 타입 안전, 동적 쿼리, 복잡 로직을 작성한다.
유지보수나 재사용성이 탁월하다. 반복/변경 가능한 동적 쿼리는 반드시 QueryDSL을 사용한다.

profile
선형의 비선형적 기록 🐜

0개의 댓글