[Spring Framework] 17강 - Dynamic SQL

seb Incode·2022년 4월 23일
0

Spring Framework

목록 보기
17/22
post-thumbnail

학습 내용

  • MyBatis 동적 SQL

학습 목표

  • 동적 SQL의 구문을 이해한다.
  • if, choose, trim, foreach를 사용하여 동적 SQL을 작성 할 수 있다.

MyBatis 동적 SQL

Dynamic SQL

검색조건에 따라 검색해야 하는 SQL문이 달라지기 때문에 이를 처리하기 위해서 동적 SQL이 사용됨

이 기능이 없으면, 각 조건에 따른 if문이 필요하기 때문에 Dynamic SQL 덕분에 소스코드가 간결해집니다. 모든 동적 SQL 처리를 xml파일에서 할 수 있다는 장점이 있습니다.

MyBatis의 표현식

  • if
  • trim(where, set)
  • choose(when, otherwise)
  • foreach

동적 SQL 작성 시 유의사항

  • MyBatis 구문을 이용하여 SQL문이 실행 시에 변경되기 때문에 모든 케이스에 대해 테스트가 이루어져야 함
  • 동적 SQL문이 없는 상태에서 정상적인 실행을 확인 후, 동적 SQL을 추가해서 개발

if

  • MyBatis에서 가장 공통적으로 사용되는 요소
<select id="findActiveBlogWithTtileLike" resultType="Blog">
  select * from blog where state='ACTIVE'
  <if test="title != null">
    and title like #{title}
  </if>
</select>
  • 위 구문은 파라미터 중 title에 값이 존재할 경우 and title like ${title} 구문을 본 쿼리문에 포함시킨다.

<select id="findActiveBlogLike" resultType="Blog">
  select * from blog where state='ACTIVE'
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>
  • 위 구문은 author와 author.name 파라미터에 값이 존재할 경우 AND author_name like ${author.name} 구문을 본 쿼리문에 포함시킨다.
  • 파라미터 타입 안에 다른 타입(클래스)이 포함되어 캡슐화를 이룰 경우 ".(점)" 연산자로 접근할 수 있다.

if문 예시입니다.
if 태그 내 test 속성 값이 참일 때
if 태그 안 내용 "AND title like ${title}" 구문이 같이 실행됩니다.
만약 if문이 없었다면 별도의 두 개의 sql문이 필요했을 겁니다..

choose(when, otherwise)

  • 여러 구문 중 하나만 실행
<select id="findActiveBlogLike" resultType="Blog">
  select * from blog where state='ACTIVE'
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = -1
    </otherwise>
  </choose>
</select>
  • title 파라미터의 값이 존재하면 AND title like #{title} 구문을 포함
  • author와 author.name 파라미터 값이 존재하면 AND author_name like #{author.name} 구문을 포함.
  • 둘 다 존재하지 않다면 AND featured = -1 구문을 포함.

trim(where, set)

  • 여러 구문 중 하나만 실행한다
    ↓ 틀린 예시
<select id="findActiveBlogLike" resultType="Blog">
  select * from blog
  where
  <if test="state != null">
    state = #{state}
  </if>
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>
  • 만약 아무런 파라미터도 없다면 아래와 같은 쿼리가 만들어짐
select * from blog where
  • 두 번째 조건만 해당된다면 아래와 같은 쿼리가 만들어짐
select * from blog
where AND title like #{title}
  • 모두 실행할 수 없는 쿼리가 만들어짐
  • 때문에 trim을 사용해야 함
<select id="findActiveBlogLike" resultType="Blog">
  select * from blog
  <where>
    <if test="state != null">
      state = ${state}
    </if>
    <if test="title != null">
      AND title = #{title}
    </if>
    <if test="author != null and author.name != null">
      AND author_name like #{author.name}
    </if>
  </where>
</select>

마지막 소스코드의 경우, 모든 if문이 false면 "select * from blog"가 쿼리문이 됩니다. 발생할 수 있는 에러 하나를 방지했습니다.
하지만 두 번째 if문 or 세 번째 if문만 true인 경우, 또 구문 오류가 발생합니다..

  • < where> < /where>는 내부에 컨텐츠가 존재할 때 where 키워드를 포함시킴
  • 그렇지 않을 경우는 where 키워드를 쓰지 않음
  • 또한, where 다음 and 혹은 or가 바로 올 경우 and, or 키워드를 삭제시킴
<trim prefix="WHERE" prefixOverrides="AND | OR">
  ...
</trim>
  • 혹은, 위 구문과 같이 trim을 바로 사용할 수도 있다.
<select id="findActiveBlogLike" resultType="Blog">
  select * from blog
  <trim prefix="WHERE" prefixOverrides="AND">
    <if test="state != null">
      state = ${state}
    </if>
    <if test="title != null">
      title = #{title}
    </if>
    <if test="author != null and author.name != null">
      author_name like #{author.name}
    </if>
  </trim>
</select>

trim 태그 내 if문 중 하나라도 참이면, where 절을 붙여서 SQL문을 만들어줍니다. if문이 두 개 이상 참이면, AND 구문을 추가해줍니다.

  • trim은 where절 뿐만 아니라 set 절에도 적용 가능하다.
  • < set>< /set>는 내부에 컨텐츠가 존재할 때 set 키워드를 포함시킴
  • 그렇지 않을 경우는 set 키워드를 쓰지 않음
  • 또한, set 다음 ",(콤마)"가 바로 올 경우 ",(콤마)"를 삭제시킴
<update id="updateAuthorNecessary">
  update Author
  <trim prefix="set" overrides=",">
    <if test="state != null">
      state = #{state}
    </if>
    <if test="title != null">
      title = #{title}
    </if>
    <if test="author != null and author.name != null">
      author_name = #{author.name}
    </if>
  </trim>
  where author_id = #{id}
</update>

foreach

  • Dynamic Query에서 공통적으로 필요한 기능은 Collection 의 반복 처리 기능
  • in 키워드를 사용할 때 종종 사용됨
<select id="selectPostIn" resultType="domain.blog.Post">
  select * from POST P
  where id in
  <foreach item="item" index="index" collection="list"
           open="(" separator="," close=")">
    #{item}
  </foreach>
</select>
  • collection 속성은 List일 경우는 list, array가 사용된다.
  • 파라미터가 List일 경우 "list"
  • 파라미터가 Array(배열)일 경우 "array"를 사용한다.

0개의 댓글