책 [자바 ORM 표준 JPA 프로그래밍]을 참고하여 작성하였습니다.
Spring Data JPA란
- Spring 프레임워크에서 JPA를 편리하게 사용할 수 있도록 지원하는 프로젝트이다.
- CRUD를 처리하기 위한 공통 인터페이스를 제공한다.
- repository를 개발할 때 인터페이스만 작성하면 실행 시점에 Spring Data JPA가 구현 객체를 동적으로 생성해서 주입해준다.
- Spring Data Project
- Spring Data JPA는 Spring Data Project의 하위 프로젝트 중 하나이다.
- Spring Data Project는 JPA, MongoDB, Redis 같은 다양한 DB에 대한 접근을 추상화한다.
공통 인터페이스 기능

- save
- 새로운 엔티티는 저장하고 이미 있는 엔티티는 수정.
- 식별자 값이 null이면 새로운 엔티티로 판단하여 내부에서 EntityManager.persist() 호출. 아니면 이미 있는 엔티티로 판단해서 EntityManager.merge() 호출.
- delete
- 내부에서 EntityManager.remove() 호출
- fineOne
- 엔티티 하나 조회
- 내부에서 EntityManager.find() 호출
- getOne
- 엔티티를 프록시로 조회
- 내부에서 EntityManager.getReference() 호출
- findAll
- 모든 엔티티를 조회.
- Sort나 Pageable 조건을 파라미터로 줄 수 있다.
쿼리 메소드 기능
1) 메서드 이름으로 쿼리 생성
- 정해진 규칙에 따라 메서드 이름을 작성하면, JPA는 이를 분석해서 자동으로 JPQL을 생성하고 실행한다.



출처 : https://docs.spring.io/spring-data/jpa/docs/current/reference/html/
2) JPA NamedQuery
- 쿼리에 이름을 부여해서 사용하는 방식
- 아래와 같이 어노테이션으로 정의하거나 xml에 쿼리를 정의할 수 있다.
- Spring Data JPA는
도메인 클래스 + .(점) + 메소드 이름으로 Named 쿼리를 찾아서 실행
- 만약 실행할 Named 쿼리가 없다면 메서드 이름으로 쿼리 생성 전략을 사용
@Entity
@NamedQuery(
name = "Member.findByUsername",
query = "select m from Member m where m.username =: username")
public class Member {
...
}
3) @Query, 리포지토리 메서드에 쿼리 정의
- 리포지토리 메서드에 직접 쿼리를 정의
- 장점 : JPA Named 쿼리처럼 애플리케이션 실행 시점에 문법 오류를 발견할 수 있음.
- 네이티브 SQL를 사용하려면 @Query 애노테이션에
nativeQuery = true를 설정한다.
4) 파라미터 바인딩
- Spring Data JPA는 위치 기반 파라미터 바인딩과 이름 기반 파라미터 바인딩을 모두 지원
- 기본값은 위치 기반(파라미터 순서로 바인딩)
- 이름 기반 파라미터 바인딩을 사용하려면 @Param 애노테이션을 사용
select m from Member m where m.username = ?1 //위치기반
select m from Member m where m.username = :name //이름기반
5) 벌크성 수정 쿼리
- @Modifyiing 애노테이션으로 벌크성 수정, 삭제 쿼리 사용
- 벌크성 쿼리 실행 후에 영속성 컨텍스트를 초기화하고 싶으면
@Modifying(clearAutomatically =true)로 설정
6) 반환 타입
- 결과가 한 건 이상이면 컬렉션 인터페이스(List) 사용, 단건이면 반환타입 지정
- 조회 결과가 없으면 컬렉션은 빈 컬렉션 반환, 단건이면 null 반환
7) 페이징과 정렬
org.springframework.data.domain.Sort : 정렬 기능
org.springframework.data.domain.Pageable : 페이징 기능(내부에 Sort 포함)
- Pageable 파라미터를 설정하면 반환 타입으로 List나
org.springframework.data.domain.Page를 사용할 수 있음
- Page를 사용하면 페이징 기능을 제공하기 위해 검색된 전체 데이터 건수를 조회하는 count 쿼리를 추가로 호출
- Pageable은 인터페이스. 따라서 실제 사용할 때는
PageRequest 객체를 사용.
- 첫번째 파라미터 : 현재 페이지
- 두번째 파라미터 : 조회할 데이터 수
- 추가로 Sort 정보도 사용 가능(예: Direction.DESC)
Page<Member> findByName(String name, Pageable pageable);
List<Member> findByName(String name, Pageable pageable);
List<Member> findByName(Stirng name, Sort sort);
PageRequest pageRequest = new PageRequest(0, 10, new Sort(Direction.DESC, "name"));
Page<Member> result =
8) 힌트
- @QueryHints : JPA 쿼리 힌트를 위한 애노테이션
@QueryHints(value = { @QueryHint(name = "org.hibernate.readOnly", value = "true")}, forCounting = true)
Page<Member> findByName(String name, Pageable pageable);
9) Lock
@Lock(LockModeType.PESSIMISTIC_WRITE)
List<Member> findByNAme(String name);
사용자 정의 repository 구현
사용자 정의 인터페이스
public interface MemberRepositoryCustom {
public List<Member> findMemberCustom();
사용자 정의 구현 클래스
public class MemberRepositoryImpl implements MemberRepositoryCustom {
@Override
public List<Member> findMemberCustom(){
//사용자정의 구현
}
}
사용자 정의 인터페이스 상속
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom
✅실제로 프로젝트에서 Spring Data JPA와 QueryDsl을 함께 사용하기 위해 다음과 같은 방식으로 구현했었다.
WordRepository.java

WordRepositoryCustom.java

WordRepositoryImpl.java

QueryDSL과 Spring Data JPA 통합
QueryDslPredicateExecutor
- repository에서 QueryDslPredicateExecutor 상속 받아 사용
- 단점 : join, fetch 사용 불가
QueryDslRepositorySupport
- QueryDsldsl의 모든 기능을 사용하기 위한 방법
- JpaRepository를 상속받는 인터페이스 만들기 (예: MemberRepository)
- 커스텀한 메서드를 정의하는 repository 인터페이스를 만들기(예: MemberRepositoryCustom)
- MemberRepositoryCustom을 구현, QueryDslRepositorySupport을 상속하는 MemberRepositoryImpl 클래스를 만든다.
잘 읽었습니다. 좋은 정보 감사드립니다.