웹개발/SpringBoot

Jpa Repository

bergerac 2025. 5. 22. 09:11

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