본문 바로가기

MyBatis/Dynamic SQL

MyBatis Dynamic SQL

MyBatis 3 Dynamic SQL ( 동적 SQL )


http://mybatis.github.io/mybatis-3/ko/dynamic-sql.html

http://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte2:psl:dataaccess:mybatis_dynamic_sql


MyBatis-3-User-Guide_ko.pdf


한글 매뉴얼 42 페이지 참조


MyBatis를 사용하지 않을 때의 동적 SQL 사용 예


String sql = "select * from emp ";


if( category==null || category.equals("") ) {


}

else if(category.equals("empno")) {

  sql += "where empno=?";

  pstmt = conn.prepareStatement(sql);

  pstmt.setInt(1, empno);

}

else if(category.equals("deptno")) {

  sql += "where deptno=?";

  stmt = conn.prepareStatement(sql);

  pstmt.setInt(1, deptno);

}


ResultSet rs = pstmt.executeQuery();



MyBatis 3에서 제공하는 동적 SQL  예

if
여러 조건을 제시하고 일치하는 모든 조건(다수개 가능)에 따라서 동적으로 SQL 문장이 완성된다

한개의 if를 사용한 경우
<select id=”getEmp” parameterType=”Emp” resultType=”Emp”>
  SELECT * FROM emp
  <if test=”empno!= null”>
    WHERE empno=#{empno}
  </if>
</select>


다수개의 if를 사용하여 동시에 2개 이상의 조건이 실행될 수 있는 경우

<select id=”getEmp” parameterType=”Emp” resultType=”Emp”>

  SELECT * FROM emp WHERE 1=1

  <if test=”empno != 0”>

    AND empno=#{title}

  </if>

  <if test=”deptno != 0”>

    AND deptno=#{deptno}

  </if>

  <if test="ename != null">

    AND ename LIKE '%' || #{ename} || '%'

  </if>

</select>



여러개의 조건 중에서 한개의 조건만 적용하는 경우

choose, when, otherwise


<select id="getEmpList" parameterType="EmpVO" resultType="EmpVO">

  SELECT * FROM EMP WHERE JOB = ‘Manager’

  <choose>

    <when test=”mgr != 0”>

      AND mgr like #{mgr}

    </when>

    <when test=”empno != 0 and ename !=null”>

      AND ename like #{ename}

    </when>

    <otherwise>

      AND ename != 'KING'

    /otherwise>

  </choose>

</select>



동적으로 생성된 SQL 문장에서 발생하는 오류의 예

아래의 문장에서 두번째 if 조건만 일치하는 경우에는 다음 라인과 같은 잘 못된 SQL 문장이 생성된다

SELECT * FROM emp WHERE AND deptno=#{deptno}

<select id=”findEmp” parameterType=”Emp” resultType=”Emp”>

  SELECT * FROM emp

WHERE

<if test=”ename != null”>

  ename = #{ename}

</if>

<if test=”deptno != 0”>

  AND deptno=#{deptno}

</if>

</select>



위에서 발생하는 문제점을 해결하기 위해서 다음과 같은 방법을 사용할 수 있다

<where> 사용하면 where를 단순하게 삽입해주고 만약에 where 절이AND, OR 으로 시작되는 경우에 AND, OR를 삭제해준다


<select id=”findEmp” parameterType=”Emp” resultType=”Emp”>

SELECT * FROM emp

<where>

<if test=”ename != null”>

  ename = #{ename}

</if>

<if test=”deptno != 0”>

  AND deptno=#{deptno}

</if>

</where>

</select>



<where>의 기능이 기대에 미치지 못한다면 다음과 같이 <trim>을 사용할 수도 있다


<select id=”findEmp” parameterType=”Emp” resultType=”Emp”>

SELECT * FROM emp

<trim prefix="WHERE" prefixOverrides="AND |OR ">

  <if test=”ename != null”>

    ename = #{ename}

  </if>

  <if test=”deptno != 0”>

    AND deptno#{deptno}

  </if>

</trim>

</select>



<set> 은 단순히 set 을 삽입하고 불필요한 콤마(,)를 제거해준다


<update id="updateEmp" parameterType="Emp">

update emp

<set>

  <if test="deptno != 0">deptno=#{deptno},</if>

  <if test="sal != 0">sal=#{sal},</if>

  <if test="comm != 0">comm=#{comm},</if>

  <if test="mgr != 0">mgr=#{mgr}</if>

</set>

where empno=#{empno}

</update>




<foreach>

MyBatis 의 메소드를 호출할 때 파라미터로 List나 배열을 전달할 수 있는데, 이 때 MyBatis는 전달된 List 나 배열을 Map에 저장하고 키로 'list' 혹은 'array' 를 사용한다.


<select id="getEmpList" resultType="Emp">

SELECT * FROM emp WHERE empno IN

<foreach item="item" index="index" collection="list" open="(" separator="," close=")">

#{item}

</foreach>

</select>



만약 파라미터 오브젝트가 변수로 컬렉션을 포함하고 있는 경우에는 'list', 'array' 가 아니라 해당 변수의 이름을 사용하면 된다.

MyBatis 메소드를 호출할 때 Param 이라는 클래스의 오브젝트를 파라미터로 전달할 때 conditions 라는 List 형의 변수가 포함되어 있다면...


<select id="getEmpList" parameterType="Param" resultType="Emp">

SELECT * FROM emp

WHERE empno IN

<foreach item="item" index="index" collection="conditons"

  open="(" separator="," close=")">

  #{item}

</foreach>

</select>