특정 범위의 객체를 검색하거나, like 처리가 필요한 경우, 여러 검색 조건이 필요할 때를 위해 Spring Data JPA는 다음의 방법을 제공한다.
쿼리 메서드 : 메서드의 이름 자체가 쿼리의 구문으로 처리되는 기능
@Query : SQL과 유사하게 엔티티 클래스의 정보를 이용해서 쿼리를 작성하는 기능
Querydsl 등의 동적 쿼리 가능 (다음에 다룰 예정)
Reference https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation
List<Memo> findByMnoBetweenOrderByMnoDesc(Long from, Long to);
작성된 메서드 이름을 보면 mno를 기준으로 해서 between 구문을 사용하고 order by가 적용될 것임을 알 수 있다.
테스트 코드
@Test
public void testQueryMethods(){
//번호역순으로 50번과 60번사이대 리스트
// List<Memo> list = memoRepository.findByMnoBetweenOrderByMnoDesc(50L, 60L);
// for(Memo memo : list){
// log.info(memo);
// }
List<Memo> findByMnoBetweenOrderByMnoDesc(Long from, Long to);
Page<Memo> findByMnoBetween(Long from, Long to, Pageable pageable);
테스트 코드
Sort sort = Sort.by("mno").descending();
Pageable pageable = PageRequest.of(1, 10, Sort.by("mno").descending());
Page<Memo> result = memoRepository.findByMnoBetween(50L, 70L, pageable);
for (Memo memo : result){
log.info(memo);
}
void deleteMemoByMnoLessThan(Long num);
테스트 코드
@Test
@Transactional
@Commit
public void testDeleteQueryMethods(){
memoRepository.deleteMemoByMnoLessThan(10L);
}
쿼리 메소드는 검색과 같은 기능을 작성할 때 편리하다.
하지만 조인이나 복잡한 조건을 처리할 때는 'And, Or'등이 사용되면서 복잡해진다.
일반적인 경우에는 간단한 처리만 쿼리 메소드를 이용하고, @Query를 이용하는 경우가 더 많다.
@Query는 메서드 이름과 상관없이 메소드에 추가한 어노테이션을 통해 원하는 처리가 가능하다.
@Query의 value는 JPQL(Java Persistence Query Language)로 작성한다.
JPQL은 객체 지향 쿼리라고 불리는 구문이다.
@Query의 기능
객체 지향 쿼리는 테이블 대신 엔티티 클래스를 이용한다.
테이블의 칼럼 대신에 클래스에 선언된 필드를 이용해서 작성한다.
JPQL은 SQL과 상당히 유사하다.
예를 들어 'mno의 역순으로 정렬하라'는 다음과 같은 형태가 된다.
@Query("select m from Memo m order by m.mno desc")
List<Memo> getListDesc();
예를 들어 ':파라미터'를 이용하는 방식은 다음과 같다.
@Transactional
@Modifying
@Query("update Memo m set m.memoText = :memoText where m.mno = :mno")
int updateMemoText(@Param("mno") Long mno, @Param("memoText") String memoText);
만일 ':'를 이용하는 경우는 여러 개의 파라미터를 전달할 때 복잡해 질 경우가 있다고 생각된다면 ':#'를 이용해 객체를 사용할 수 있다.
@Transactional
@Modifying
@Query("update Memo m set m.memoText = :#{#param.memoText} where m.mno = :#{#param.mno}")
int updateMemoText(@Param("param") Memo memo);
@Query(value= " select m from Memo m where m.mno > :mno",
countQuery = "select count(m) from Memo m where m.mno > :mno"
)
Page<Memo> getListWithQuery(Long mno, Pageable pageable);
@Query(value = "select m.mno, m.memoText, current_date from Memo m where m.mno > :mno",
countQuery = "select count(m) from Memo m where m.mno > :mno"
)
Page<Object[]> getListWithQueryObject(Long mno, Pageable pageable);
테스트 코드
Page<Object[]> listWithQueryObject = memoRepository.getListWithQueryObject(34L, pageable);
listWithQueryObject.forEach(m -> {
Long mno = (Long) m[0];
String memoText =(String) m[1];
Date current_date = (Date) m[2];
log.info("번호 : " + mno + " 메모내용 : " + memoText +" 메모 시간 : " + current_date);
});
//NativeQuery
@Query(value = "select * from tbl_memo where mno > 0", nativeQuery = true)
List<Object[]> getNativeResult();