JpaRepository는 Spring Data JPA에서 제공하는 데이터 액세스 계층의 기본 인터페이스다. 이걸 상속받기만 하면, 직접 SQL을 작성하지 않아도 대부분의 CRUD 작업을 메서드 하나로 해결할 수 있게 된다.
public interface UserRepository extends JpaRepository<User, Long> {
}
1. CRUD 메서드 사용법
JpaRepository가 제공하는 기본적인 CRUD 메서드는 다음과 같다:
- save(E entity): 새 엔티티 저장 또는 기존 엔티티 수정
- findById(ID id): ID로 엔티티 조회 (Optional로 반환)
- existsById(ID id): 해당 ID 존재 여부 반환
- findAll(): 모든 데이터 조회
- deleteById(ID id): 해당 ID의 데이터 삭제
userRepository.save(new User("bergerac", "bergerac@example.com"));
Optional<User> user = userRepository.findById(1L);
cf. 제네릭 타입 설명
- E: 엔티티 클래스 (예: User)
- ID: 해당 엔티티의 PK 타입 (예: Long)
2. Query Method
구조
Optional<User> findByUsername(String username);
List<Product> findByPriceGreaterThan(int price);
키워드
- findBy: SELECT문 시작
- And, Or: 조건 결합
- Between, LessThan, GreaterThanEqual 등: 비교 연산
- IsNull, IsNotNull: null 체크
- Like, Containing, StartingWith: 패턴 검색
- In, NotIn: 리스트 검색
- OrderBy: 정렬 조건 지정
예시
List<Product> findByPriceGreaterThanEqual(int price);
//가격이 5000원 이상인 상품 조회
List<Product> findByNameContaining(String keyword);
//이름에 keyword가 포함된 상품 조회
List<Product> findByCategoryAndPriceBetween(String category, int min, int max);
//특정 카테고리에서 가격이 min과 max 사이인 상품 조회
3. @Query
- JOIN이 포함된 복잡한 쿼리
- 서브쿼리나 그룹핑이 필요한 상황
- 동적으로 정렬하거나 계산이 필요한 경우
- 메서드 이름이 너무 길어져 가독성이 떨어질 때
@Query("SELECT u FROM User u WHERE u.username = :username")
Optional<User> findByUsername(@Param("username") String username);
- @Query: 쿼리를 직접 작성
- :파라미터명: 파라미터 바인딩
- @Param: 메서드 파라미터와 쿼리 내 파라미터를 매핑
※ JPQL은 SQL과 비슷하지만, 테이블이 아닌 Entity 이름과 필드는 클래스 필드 이름을 사용한다는 점이 다름
여러조건과 JOIN이 필요한 경우
@Query("SELECT o FROM Order o JOIN o.user u WHERE u.name = :name AND o.status = :status")
List<Order> findOrdersByUsernameAndStatus(@Param("name") String name, @Param("status") String status);
- JOIN은 연관관계 필드명으로 진행
- 객체를 기준으로 조회하는 방식이기 때문에 객체지향적인 JOIN이 가능
Native Query (SQL 직접 작성)
@Query(value = "SELECT * FROM users WHERE email LIKE %:keyword%", nativeQuery = true)
List<User> searchByEmailKeyword(@Param("keyword") String keyword);
- nativeQuery = true: JPQL이 아니라 실제 SQL로 처리됨
- 테이블 이름, 컬럼 이름 모두 실제 DB 기준으로 작성해야 함
- MySQL의 LIMIT, GROUP BY, UNION 등도 자유롭게 사용 가능
DTO로 결과 매핑하기
조회결과를 Entity가 아닌 DTO 로 받고 싶을때 @Query가 유용함
- new 패키지경로.클래스명(필드1, 필드2, …) 형식으로 DTO를 직접 생성
- 해당 DTO에 일치하는 생성자가 반드시 있어야 함
수정/삭제 쿼리 (@Modifying 과 함께 사용)
@Modifying
@Query("UPDATE User u SET u.status = 'DELETED' WHERE u.lastLogin < :threshold")
int markUsersInactive(@Param("threshold") LocalDateTime threshold);
- @Modifying: INSERT, UPDATE, DELETE 쿼리에는 반드시 붙여야 함
- 반환값은 int로, 영향 받은 행(row)의 개수
@Transactional
@Modifying
@Query("DELETE FROM User u WHERE u.status = 'DELETED'")
void deleteInactiveUsers();
삭제 쿼리는 @Transactional과 함께 사용해야 트랜잭션 처리 가능
'웹개발 > SpringBoot' 카테고리의 다른 글
| @Bean VS @Component (0) | 2025.05.24 |
|---|---|
| Controller Mapping Annotation (0) | 2025.05.23 |
| ORM (Object-Relational Mapping) (4) | 2025.05.21 |
| SpringBoot 활용 (0) | 2025.05.20 |
| IoC(제어의 역전),DI(의존성 주입) (1) | 2025.05.19 |