프레임워크/Spring

Dynamic Query

안싱미 2016. 4. 20. 16:04

Dynamic SQL

쿼리 내에 조건문을 이용해서 중복되는 쿼리들을 최소화시킬 수 있다.


#Dynamic Query 의 종류

  • If

  • Choose

    • Java의 else if 격

  • Trim

  • Foreach

    • 잘 사용되지 않지만 가끔 사용한다.


#if

파라미터로 받아온 값을 조건절로 거를 때 사용한다.

파라미터 타입 안에 다른 타입(클래스)가 포함되어 캡슐화를 이룰 경우 .(dot) 연산자로 변수 접근이 가능하다.


#choose

Else if 가 없기 때문에 choose로 사용한다.

<choose></choose>로 로 크게 감싸고 <when test="조건"> </when>으로 조건을 걸고 <otherwise> </otherwise>로 기타를 거른다.


#Trim(where, set)

여러 구문 중 하나만 실행할 수 있다.


SELECT *

FROM   BLOG

WHERE

<if test="state != null">

    state = #{state}

</if>

<if test="title != null">

AND    title like #{title}

</if>


이런 구문에서 모든 조건이 해당되지 않아 빠져나온다면 SQL자체가 문법상 제대로 형성되지 않아서 SQL 문법 에러가 발생할 수 있다. 그러한 단점을 해결하기 위해서 Trim을 사용한다.


#ForEach

Dynamic Query에서 공통적으로 필요한 기능은 Collection의 반복 처리 기능


<foreach collection="array" item="배열명" separator=",">

    #{배열명}

</foreach>


Collection에는 배열이나 리스트만 사용이 가능하다 item은 파라미터 명을 적어주면 되고

Separator는 안에 담긴 Object들을 구분 시켜줄 기호이다




# 실습


1. firstName을 줄때가 있고, 안줄때가 있다고 할때 처리하는 방법


  • If를 사용하여 조건을 건다.

  • 또한 SELECT 에 보면 주석이 있는데 어떤 DAO에서 사용하는 건지와 작성 날짜를 적어주면 좋다.


쿼리 결과를 확인하기 위해서 ArticleDAOImpl에서 FirstName을 주석처리한다면 조건이 사라진 쿼리로 실행이 된다. 그렇기 때문에 하나의 쿼리로 두가지 상황의 쿼리를 생성할 수 있다.



결과는 다음과 같이 firstName을 주석처리해서 없으니 컬럼들이 조건절에 따라서 없어진 결과를 보여준다.



2.DEPARTMENTS에서 부서명을 더 가져오는 방법


아래와 같이 작성한다면, firstName이 있을 때 부서명을 출력할 수 있다.



departmentName을 출력할 수 있게 VO에 departmentName 변수를 선언하고, getter setter를 추가해준다.


그리고 jsp 에서 출력하는 구문을 추가한다.


그리고 실행을 해보면 아래처럼 잘 실행이 된다.


3. If를 choose when otherwise로 바꾸어서 똑같이 동작하는지 실행해본다.


실행해보면 2. 결과와 동일한 화면을 볼 수 있다.


4. Otherwise, when 절을 걸어보기

departmentName 이 찍히지 않는 것을 볼 수 있다.

이제는 when절을 하나 더 걸어서 두개의 조건으로 어떠한 쿼리가 생성되는지 테스트해본다.


현재 firstName 이 없으므로 2번의 쿼리가 실행된다.


실행을 해보면, 다음과 같다.



그러면 이제는 1번의 쿼리와 2번의 쿼리가 모두 참일 때 어떤 쿼리가 실행되는지 체크해본다.

이를 위해 다시 firstName의 주석을 풀고 다시 실행을 해본다.


결과는 다음과 같이 첫번째 when 절만 실행된 것을 볼 수 있다. When에서 첫번째로 걸린 쿼리를 사용한다.


5. Trim 이용하여 Last name을 조건절로



테스트를 진행하기 위해 lastName을 주석처리한 뒤 실행해본다.



이렇게 하면 에러가 발생한다. SQLSyntaxErrorException이 발생하는 것은, where절 이후에 lastName이 없어서 바로 and가 나오기 때문이다. 이를 해결하기 위해 3가지 방법이 있다.


  1. Where 절에 1=1 을 넣으면 무조건 참이 되고 그 외의 추가 조건들을 AND로 붙여버린다. 그러면 where절에는 무조건 에러가 발생하지 않고 AND 를 통해서 조건절에서 참인것만 추가가 되게 된다.

2) 하지만 위와 같은 방식은 잘 사용하지 않고 아래와 같은 방식으로 해결할 수도 있다.


이렇게 하면 if 구절에 참이 없다면 where 가 붙지 않게 된다. 그리고 firstName의 주석을 지우고 다시 실행을 해본다. 그렇다면 쿼리는 다음과 같이 작성된 것을 볼 수 있다.


WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID AND FIRST_NAME = ?


3) 더욱 편하게 사용을 하려면 trim을 사용하는 것도 볼 수 있다.