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
한글 매뉴얼 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();
다수개의 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>