(JPA - 7) Spring Data JPA

MyBatis나 JDBC로 데이터 엑세스 계층을 개발하다보면 테이블 단위의 단순 CRUD 코드가 반복되고,
조회 조건에 따라 findByXXXandYYY() 와 같은 메소드와 매핑된 SQL이 늘어난게 된다.

Spring Data JPA는 CRUD와 같은 공통 인터페이스를 제공하고,
findByXXXandYYY() 와 같은 메소드를 인터페이스에 정의만 해두면,
실행시점에 구현 객체를 만들어서 주입해 준다.

1
2
3
4
5
6
7
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}

@Service
public class EmployeeService {
@Autowired EmployeeRepository employeeRepository; // 실행시점에 구현체 자동 생성 후 주입
}
  • JpaRepository<T, ID>
    fig

쿼리 메소드 기능

  • 메소드 이름으로 쿼리 자동 생성
    위의 예제에서 EmployeeRepository에 Employee의 이름과 나이로 조회를 하고 싶다면 아래와 같이 추가만 해주면 된다.

    1
    2
    3
    public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    Employee findByNameAndAge(String name, Integer age); // 메소드 이름 규칙에 따라 쿼리 자동 생성
    }

    Spring Data JPA 쿼리 메소드 생성 규칙 을 참조 하자.

  • 메소드 이름으로 NamedQuery 호출
    엔티티 명 + .(dot) + 메소드 이름으로 NamedQuery를 찾는다.
    없으면 위와 같이 메소드 이름 규칙에 따라 쿼리를 생성한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Entity
    @Table(name="EMPLOYEE")
    @NamedQuery(
    name="Employee.findByNameAndAge",
    query="select e from EMPLOYEE e where e.name= :name and e.age= :age"
    )
    public class Employee {....}

    public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    Employee findByNameAndAge(@Param("name") String name, @Param("age") Integer age); // NamedQuery 호출
    }
  • 메소드에 @Query 어노테이션을 활용해 쿼리 직접 정의

    1
    2
    3
    4
    5
    6
    7
    public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    @Query("select e form Employee e where e.name = ?1") // 1부터 시작
    Employee findByName(String name);

    @Query(value="select * from EMPLOYEE where age = ?0", nativeQuery=true) // 네이티브 쿼리는 0 부터 시작
    Employee findByAge(String age);
    }

NOTE
JPA는 위 예제와 같이 두가지 파라메터 바인딩 을 지원한다.
위치 기반 : … where e.name = ?1
이름 기반 : … where e.name = :name – <== @Param(“name”)

페이징, 정렬 기능

  • 페이징 : org.springframework.data.domain.Pageable
    1
    2
    3
    4
    public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    Page<Employee> findByName(String name, Pageable pageable); // Page 객체로 리턴
    List<Employee> findByAge(Integer age, Pageable pageable); // List 객체로 리턴
    }
  • 정렬 : org.springframework.data.domain.Sort
    1
    2
    3
    public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    List<Employee> findByAge(Integer age, , Sort sort);
    }
1
2
PageRequest page = new PageRequest(0, 10, new Sort(Direction.DESC, "name"));
Page<Employee> result = employeeRepository.findByName("kihoon", page);
Share