너무 잘되어 있는 포스트가 있어 아래에 전체 링크함. 필요한 케이스는 다 들어가있는 듯.
요약
@Query 어노테이션을 달고 일반 SQL 및 JPQL로 쿼리를 작성할 수 있다.
JPQL은 JPA에서 지원하는 객체지향 쿼리 언어이다. 테이블 명 등으로 작성하는 일반 sql과 달리 JPA에서 생성한 Entity 등으로 참조한다.
함수명은 일반 JPA처럼 결정되어 있는 것이 아니라 임의작성가능(길이를 줄일 수 있다!!! 망할 JPA!!!)
기본값은 JPQL로 작성가능하고 일반 SQL로 작성하려면 옵션(nativeQuery = true, default false)을 바꿔야한다.
@Query(nativeQuery = true)
예제
select * from user where id='test01'
이 문구를 적용해본 6가지 케이스는 아래와 같다.
querydsl과 가장 차별화되는 부분은 from 절에 alias를 사용할 수 있다는 점인 것 같다.
@Repository
public interface IUsrRepository extends JpaRepository<Usr, String> {
// 일반 JPA
Usr findById(String id);
// 일반 SQL 사용
@Query(value="select * from user u where u.id=?1", nativeQuery=true)
Usr findUsr1(String id);
// 일반 SQL에 파라미터 지정 사용
@Query(value="select * from user u where u.id=:id", nativeQuery=true)
Usr findUsr2(@Param(value=id)String id);
// 일반 SQL에 객체 파라미터 사용
@Query(value="select * from user u where u.id=:#{#userInfo.id}", nativeQuery=true)
Usr findUsr3(@Param(value=userInfo)UserInfo info);
// JPQL 사용
@Query("select * from from Usr u where u.id=?1")
Usr findUsr4(String id);
// JPQL 사용에 파라미터 지정 사용
@Query("select * from from Usr u where u.id=:id")
Usr findUsr5(@Param(value=id)String id);
// JPQL 사용에 객체 파라미터 사용
@Query(value="select * from Usr u where u.id=:#{#userInfo.id}")
Usr findUsr6(@Param(value=userInfo)UserInfo info);
}
그 외 select 가 아닌 update나 delete를 하려면 추가적인 어노테이션이 필요하다.
그 부분은 하단 참조 포스트의 본문 중 해당 부분을 기재한다.
@Modifying / @Transactional
위의 쿼리처럼 select구문이 아닌 DML(insert, update, delete) 구문을 사용할 때는 다음의 어노테이션을 추가적으로 사용해야 됩니다.
- @Modifying
- @Transactional
먼저 @Modifying은 insert, update, delete 뿐만 아니라 DDL구문을 사용할 때도 표기를 해줘야 됩니다.
왜냐하면 영속성 컨텍스트에 오래된 데이터를 비워주고 새로운 데이터를 읽어오기 위해서입니다.
그리고 @Transactional은 update, delete를 할 때 표기를 해줘야 정상 실행이 됩니다.
update구문으로 예제 코드를 만들어 보겠습니다.
- Repository
package com.spring.jpa.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
import com.spring.jpa.dto.Snack;
public interface SnackRepository extends JpaRepository<Snack, Integer>{ // 제네릭 타입: <엔티티 클래스, 엔티티클래스의 기본키>
// JPQL은 엔티티의 변수명이 id이기 때문에 조건절에 sn.id
// JPQL 쿼리
@Query(value = "update Snack set name = :#{#paramSnack.name}, price = :#{#paramSnack.price} where id = :#{#paramSnack.id}")
@Modifying
@Transactional
public int updateJPQL(@Param(value = "paramSnack") Snack snack);
// SQL은 테이블의 컬럼명이 snack_id이기 때문에 조건절에 snack_id
// SQL 쿼리
@Query(value = "update snack set name = :#{#paramSnack.name}, price = :#{#paramSnack.price} where snack_id = :#{#paramSnack.id}", nativeQuery = true)
@Modifying
@Transactional
public int updateSQL(@Param(value = "paramSnack") Snack snack);
}
참조
댓글