본문 바로가기
Spring

[JPA] @Query annotaion 으로 직접 쿼리 작성

by 루에 2022. 8. 4.
반응형

너무 잘되어 있는 포스트가 있어 아래에 전체 링크함. 필요한 케이스는 다 들어가있는 듯.

 

요약

@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);
}

 

참조

https://jforj.tistory.com/90

반응형

댓글