Contents
see List작성일 2025. 11. 30.
Spring Data JPA 쿼리 메서드 완벽 가이드
Spring Data JPA의 쿼리 메서드를 활용하면 SQL 없이 메서드 이름만으로 복잡한 쿼리를 작성할 수 있습니다.
기본 쿼리 메서드
public interface UserRepository extends JpaRepository<User, Long> {
// 기본 조회
Optional<User> findByEmail(String email);
List<User> findByName(String name);
// 복합 조건
List<User> findByNameAndAge(String name, int age);
List<User> findByNameOrEmail(String name, String email);
// 비교 연산
List<User> findByAgeGreaterThan(int age);
List<User> findByAgeLessThanEqual(int age);
List<User> findByAgeBetween(int start, int end);
// NULL 처리
List<User> findByNicknameIsNull();
List<User> findByNicknameIsNotNull();
// LIKE 검색
List<User> findByNameContaining(String keyword);
List<User> findByNameStartingWith(String prefix);
List<User> findByNameEndingWith(String suffix);
// IN 절
List<User> findByAgeIn(Collection<Integer> ages);
// 정렬
List<User> findByNameOrderByAgeDesc(String name);
// 페이징
Page<User> findByAge(int age, Pageable pageable);
// Top/First
List<User> findTop5ByOrderByCreatedAtDesc();
Optional<User> findFirstByNameOrderByAgeDesc(String name);
// 존재 여부
boolean existsByEmail(String email);
// 개수
long countByAge(int age);
// 삭제
void deleteByEmail(String email);
}@Query 어노테이션
// JPQL
@Query("SELECT u FROM User u WHERE u.email LIKE %:domain")
List<User> findByEmailDomain(@Param("domain") String domain);
// Native Query
@Query(value = "SELECT * FROM users WHERE created_at > :date", nativeQuery = true)
List<User> findRecentUsers(@Param("date") LocalDateTime date);
// 업데이트
@Modifying
@Query("UPDATE User u SET u.status = :status WHERE u.id = :id")
int updateStatus(@Param("id") Long id, @Param("status") String status);
// DTO 프로젝션
@Query("SELECT new com.example.UserDto(u.name, u.email) FROM User u")
List<UserDto> findAllUserDto();페이징과 정렬
// 서비스 계층
Pageable pageable = PageRequest.of(0, 10, Sort.by("createdAt").descending());
Page<User> page = userRepository.findByAge(25, pageable);
// 결과 활용
List<User> users = page.getContent();
long total = page.getTotalElements();
int totalPages = page.getTotalPages();
boolean hasNext = page.hasNext();동적 쿼리 (Specification)
public class UserSpecification {
public static Specification<User> hasName(String name) {
return (root, query, cb) ->
name == null ? null : cb.equal(root.get("name"), name);
}
public static Specification<User> ageGreaterThan(Integer age) {
return (root, query, cb) ->
age == null ? null : cb.greaterThan(root.get("age"), age);
}
}
// 사용
List<User> users = userRepository.findAll(
Specification.where(hasName("Kim")).and(ageGreaterThan(20))
);프로젝션 (필요한 필드만)
// 인터페이스 프로젝션
public interface UserSummary {
String getName();
String getEmail();
}
List<UserSummary> findByAge(int age);
// 클래스 프로젝션 (DTO)
public record UserDto(String name, String email) {}
@Query("SELECT new com.example.UserDto(u.name, u.email) FROM User u")
List<UserDto> findAllDto();N+1 문제 해결
// Fetch Join
@Query("SELECT u FROM User u JOIN FETCH u.orders WHERE u.id = :id")
Optional<User> findByIdWithOrders(@Param("id") Long id);
// EntityGraph
@EntityGraph(attributePaths = {"orders", "addresses"})
Optional<User> findById(Long id);spring
| No | 작성일 | Title |
|---|---|---|
| 3360 | 2026. 08. 15. | Spring Boot Actuator와 Micrometer로 장애 징후를 먼저 찾는 운영 모니터링 구성 |
| 3328 | 2026. 08. 06. | Spring Boot 예외 처리 표준화 가이드: ProblemDetail로 일관된 API 오류 응답 만들기 |
| 3296 | 2026. 07. 29. | Spring Boot 로그인 API 보안 설계: 세션 없이 JWT를 안전하게 검증하는 방법 |
| 3265 | 2026. 07. 21. | Spring Boot API 장애 원인 빨리 찾기: Actuator와 Micrometer 관측성 구성 가이드 |
| 3238 | 2026. 07. 13. | Spring Boot 안정적인 외부 API 연동: WebClient·Circuit Breaker·Retry를 함께 운영하는 실전 가이드 |
| 3182 | 2026. 07. 04. | Spring Boot 무중단 배포를 위한 Graceful Shutdown과 Readiness Probe 설정 |
| 3137 | 2026. 06. 26. | Spring Security API 권한 설계: 공개 엔드포인트와 관리자 기능을 분리하는 실전 기준 |
| 3081 | 2026. 06. 18. | Spring Boot API 장애 추적을 위한 요청 ID와 관측 로그 설계 |
| 2992 | 2026. 06. 10. | Spring Boot 무중단 배포를 위한 준비 상태 점검과 종료 처리 설계 |
| 2935 | 2026. 06. 02. | Spring Boot Redis 캐시 운영 가이드: TTL, 무효화, 캐시 스탬피드 방지 설계 |