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 |
|---|---|---|
| 2355 | 2026. 04. 07. | Spring Boot 3.4 RestClient 완벽 가이드 - WebClient를 대체하는 동기 HTTP 클라이언트 |
| 2338 | 2026. 04. 06. | Spring Boot 3.4 Virtual Threads 실전 적용 가이드 - 설정부터 성능 최적화까지 |
| 2323 | 2026. 04. 05. | Spring Boot 4.0 + Spring Framework 7 핵심 변경사항과 마이그레이션 가이드 |
| 2300 | 2026. 04. 05. | Spring Security 7 One-Time Token 로그인과 Passkey 인증 구현 가이드 |
| 2299 | 2026. 04. 05. | Spring Boot 3.5 WebClient 글로벌 설정과 SSL 자동 구성 완벽 가이드 |
| 2273 | 2026. 04. 04. | Spring Security 6 JWT 인증 완벽 구현: SecurityFilterChain부터 리프레시 토큰까지 |
| 2271 | 2026. 04. 04. | Spring Boot 3.3 + Virtual Threads 실전 적용: 설정부터 성능 튜닝까지 |
| 2196 | 2026. 02. 11. | Spring CRaC로 애플리케이션 시작 시간 최적화 |
| 2195 | 2026. 02. 11. | Spring gRPC로 마이크로서비스 통신 구현하기 |
| 2194 | 2026. 02. 11. | Spring Observability: Micrometer와 Grafana 통합 모니터링 |