본문 바로가기
WEB/Back-end

Query Method, @Query, Querydsl(SpringBoot)

by 최새벽 2024. 7. 30.

Query Method, @Query 어노테이션

Spring Data JPA에서 검색을 위해 아래 방법을 활용할 수 있음

  • 쿼리 메서드(Query Method) : 메서드의 이름 자체가 쿼리의 구문으로 처리되는 기능
  • @Query: SQL과 유사하게 엔티티 클래스의 정보를 이용해서 쿼리를 작성하는 기능
  • Querydsl등의 동적 처리 기능

쿼리 메서드(Query Method)

https://docs.spring.io/spring-data/jpa/reference/jpa/query-methods.html

 

JPA Query Methods :: Spring Data JPA

By default, Spring Data JPA uses position-based parameter binding, as described in all the preceding examples. This makes query methods a little error-prone when refactoring regarding the parameter position. To solve this issue, you can use @Param annotati

docs.spring.io

주로 'findBy...', 'getBy...'의 형태로 시작하며 이후 필드 조건에 And, Or, Between과 같은 키워드 활용

// 다음과 같은 형식으로 활용
Page<Memo> result = memoRepository.findByMnoBetween(10L, 50L, pageable);
Page<Memo> result = memoRepository.findAll(pageable);
memoRepository.findByMemoTextContaining("i").stream().forEach(e -> {
    System.out.println(e);
});

memoRepository.deleteById(mno);
memoRepository.deleteMemoByMnoLessThan(10L);

 

 

@Query 어노테이션

속성(value값)에 JPQL 쿼리문을 담으며, 다음과 같은 작업을 실행할 수 있음.

  • 필요한 데이터만 선별적으로 추출
  • DB에 맞는 순수한 SQL(Native SQL) 사용
  • select가 아닌 DML(update, delete, insert) 등을 처리(@Modifying과 함께 사용)

테이블 대신에 엔티티 클래스, 컬럼 대신에 클래스에 선언된 필드를 이용

// 다음과 같이 사용할 수 있음
@Query("select m from Memo m order by m.mno desc"
List<Memo> getListDesc();

 

 

@Query 파라미터 바인딩

where 구문과 그에 맞는 파라미터를 처리하는 경우가 많으며 다음과 같은 방식 사용

  • ?1, ?2와 1부터 시작하는 파라미터의 순서를 이용하는 방식
  • :xxx와 같이 :파라미터 이름을 활용하는 방식
  • :#{ }와 같이 자바 빈 스타일을 이용 (해당 형태는 객체로 되어있을 때만 사용할 수 있음)

 

return 값이 Object[](Object 배열)

쿼리 메서드는 엔티티 타입의 데이터만을 추출하지만 쿼리 어노테이션은 Object[] 형태로 선별적 추출이 가능함

   select m from Memo m → m은 객체, 테이블에서 한 행이라고 생각하면 됨

JOIN이나 COUNT등 존재하지 않는 엔티티 타입을 활용해야하기 때문에 Object 배열을 유용하게 사용가능함

 

 

@Query 파라미터 사용해보기

// JPQL
// repository
@Query("select m from Memo m where memoText like %:memo% order by mno desc")
List<Memo> findMemoTextLike(String memo); // like에 있는 memo와 파라미터 memo의 이름이 동일해서 값이 들어감. 만약 이름이 다를 경우 @Param어노테이션 사용해야함

// testrepository
@Test
public void testSearch3() {
	memoRepository.findMemoTextLike("1").stream().forEach(e -> {
    	System.out.println(e);
	});
}


// Navice SQL(nativeQuery을 true로 해줘야함 기본 값 false)
// repository
@Query(value = "select * from tbl_memo where memo_text like concat('%', ?1, '%') order by mno desc", nativeQuery = true)
List<Memo> findMemoTextLike2(String memo);

// testrepository
@Test
public void testSearch4() {
	memoRepository.findMemoTextLike2("1").stream().forEach(e -> {
		System.out.println(e);
	});
}

 

 

Querydsl

동적인 SQL도 객체로 활용할 수 있게 해줌

Querydsl JPA Support, Querydsl APT Support 두 dependency 추가

// jakarta를 뒤에 붙여줘야 패키지가 javax.~~가 아닌 jakarta.~~로 나옴
implementation 'com.querydsl:querydsl-jpa:5.1.0:jakarta'
annotationProcessor(
        "jakarta.persistence:jakarta.persistence-api",
        "jakarta.annotation:jakarta.annotation-api",
        'com.querydsl:querydsl-jpa:5.1.0:jakarta'
)

 

활용

// repository
public QMemo(PathMetadata metadata) {
    super(Memo.class, metadata);
}


// testrepository
@Test
public void testQuerydsl(){
    String searchType = "t";
    String searchWord = "9";

    // 빌더 객체
    BooleanBuilder builder = new BooleanBuilder();
    QMemo memo = QMemo.memo;

    // 동적 조건
    if("t".equals(searchType)){
        builder.and(memo.memoText.like("%"+searchWord+"%"));
    }

    Page<Memo> result = memoRepository.findAll(builder, PageRequest.of(0, 10));
    result.get().forEach(e -> System.out.println(e));
}

 

 

 

* 신한DS아카데미 수강 내용 기반

* 코드로 배우는 스프링 부트 웹 프로젝트 책 기반

'WEB > Back-end' 카테고리의 다른 글

Thymeleaf 레이아웃(SpringBoot)  (0) 2024.07.30
Thymeleaf 기본(SpringBoot)  (0) 2024.07.30
(SQL) 숫자데이터 가공 함수  (0) 2024.07.29
(SQL) 함수, 문자데이터 가공 함수  (0) 2024.07.29
(SQL) SQL 표준, SELECT문  (0) 2024.07.29