by-nc-sa     개발자, DBA가 함께 만들어가는 구루비 지식창고!

Dynamic Query의 사용




Dynamic Query의 사용

1. Dynamic Query의 이해

1.1 Dynamic Query란

  • Parameter 값에 의해 쿼리를 동적으로 변환 해주는 기능이다.
  • <dynamic> 태그를 사용하여 구현 할 수 있지만 생략이 가능하다.
  • <dynamic> 태그를 사용하면, prepend, open, close 등의 속성을 사용 할 수 있다.
  • prepend : 값이 있는 경우 맨 앞에 Append 된다. (추가적인 SQL 문장)
  • open : 시작 값, prepend 다음에 붙음
  • end : 종료 값
  • ex) prepend="WHERE" open="(" end=")"

1.2 이항연산 요소

  • 대표적으로 비교연산이 있다.
연산종류 설 명 예제
<isEqual> 프로퍼티와 값 또는 다른 프로퍼티와 같은지 비교 #property# = compareValue
<isNotEqual> 프로퍼티와 값 또는 다른 프로퍼티와 같지 않은지 비교 #property# <> compareValue
<isGreaterThan> 프로퍼티와 값 또는 다른 프로퍼티보다 큰지 비교 #property# > compareValue
<isGreaterEqual> 프로퍼티와 값 또는 다른 프로퍼티보다 크거나 같은지 비교 #property# >= compareValue
<isLessThan> 프로퍼티와 값 또는 다른 프로퍼티보다 작은지 비교 #property# < compareValue
<isLessEqual> 프로퍼티와 값 또는 다른 프로퍼티보다 작거나 같은지 비교 #property# <= compareValue
이항연산 속성
  • prepend : 값이 있는 경우 맨 앞에 Append 된다. (추가적인 SQL 문장) (옵션)
  • property : 비교되는 프로퍼티 (필수)
  • compareProperty : 비교되는 다른 프로퍼티 (필수 또는 compareValue)
  • compareValue : 비교되는 값 (필수 또는 compareProperty)
  • open : 시작부분에 넣을 문자. prepend 다음에 붙음.
  • close : 끝에 넣을 문자

1.3 단항연산 요소

  • 대표적으로 널값 체크연산이 있다
연산종류 설 명
<isNull> 프로퍼티가 null인지 체크
<isNotNull> 프로퍼티가 null이 아닌지 체크
<isEmpty> Collection, 문자열 또는 String.valueOf() 프로퍼티가 null이거나 empty("" or size() < 1)인지 체크
<isNotEmpty> Collection, 문자열 또는 String.valueOf() 프라퍼티가 null이 아니거나 empty("" or size() < 1)가 아닌지 체크.
단항연산 속성
  • prepend : 값이 있는 경우 맨 앞에 Append 된다. (추가적인 SQL 문장) (옵션)
  • property : 비교되는 프로퍼티 (필수)
  • open : 시작부분에 넣을 문자. prepend 다음에 붙음.
  • close : 끝에 넣을 문자

1.4 <iterate>

  • Collection을 반복한다.
  • 주로 IN연산을 하기 위해 사용한다.
Iterate 속성
  • prepend : 값이 있는 경우 맨 앞에 Append 된다. (추가적인 SQL 문장) (옵션)
  • property : 반복되기 위한 java.util.List타입의 프라퍼티(필수)
  • open : 반복의 전체를 열기 위한 문자열, 괄호를 위해 유용하다. (옵션)
  • close : 반복의 전체를 닫기 위한 문자열, 괄호를 위해 유용하다. (옵션)
  • conjunction : 각각의 반복 사이에 적용되기 위한 문자열, IN 연산시 콤마(,) (옵션)
Iterate 예
<iterate prepend="AND" property="deptList" open="(" close=")" conjunction=",">
     #deptList[]#
</iterate> 

2. Dynamic Query 실습

2.1 검색용 모델객체(EmpSearch.java) 생성

  • 부서번호, 이름, 직업으로 검색 할 때 사용하는 EmpSearch.java 객체를 생성한다.
com.oracleclub.study.mvc.model.EmpSearch.java
package com.oracleclub.study.mvc.model;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

/**
 * 
 * @author oramaster
 */
public class EmpSearch {
	private int deptno;

	private String searchKey;
	private String searchValue;

	public int getDeptno() {
		return deptno;
	}

	public void setDeptno(int deptno) {
		this.deptno = deptno;
	}

	public String getSearchKey() {
		return searchKey;
	}

	public void setSearchKey(String searchKey) {
		this.searchKey = searchKey;
	}

	public String getSearchValue() {
		return searchValue;
	}

	public void setSearchValue(String searchValue) {
		this.searchValue = searchValue;
	}

	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}

}

2.2 사원목록 조회 SQL 문 수정

  • 사원목록 조회시 조건에 맞는 검색을 지원할 수 있도록 Dynamic Query를 사용하여 수정한다.
  • 검색용 모델객체인 EmpSearch 객체를 typeAlias로 등록한다.
  • selectEmpList에 parameterClass로 EmpSearch 객체를 전달 받는다.
  • selectEmpList에 검색 조건절을 추가한다.
/src/main/resources/sqlmap/Emp.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="emp">

  	<typeAlias alias="emp" type="com.oracleclub.study.mvc.model.Emp"/>
  	<typeAlias alias="empSearch" type="com.oracleclub.study.mvc.model.EmpSearch"/>

 	<select id="selectEmpList" resultClass="emp" parameterClass="empSearch" cacheModel="cachemodel.empCache" >
 	<![CDATA[
		SELECT empno, ename, job, sal, NVL(mgr,0) mgr
		  FROM emp 
		 WHERE empno > 0
	]]> 	 		 
		<isNotEqual property="deptno" compareValue="0" >	  
	       AND deptno = #deptno#	    
	    </isNotEqual>
	   
	    <isNotEmpty property="searchValue"> 
	        <isEqual property="searchKey" compareValue="ename">
		       AND ename LIKE '%'||#searchValue#||'%'
		    </isEqual>
		    
		    <isEqual property="searchKey" compareValue="job">
		       AND job LIKE '%'||#searchValue#||'%'
		    </isEqual>	
	    </isNotEmpty>
 	</select> 	

    <select id="selectEmp" resultClass="emp" parameterClass="int"  >
		SELECT empno, ename, job, sal, NVL(mgr,0) mgr, deptno  
		  FROM emp 
		 WHERE empno = #empno#
 	</select> 
 	
	<insert id="insertEmp"  parameterClass="emp"  >
 	    INSERT INTO emp (empno, ename, job, sal, mgr,  hiredate, deptno)
        VALUES (#empno#, #ename#, #job#, #sal#, 0, #hiredate#, #deptno#)
    </insert> 
  	
</sqlMap>

2.3 EmpDAO.java 수정

  • selectEmpList 메소드에서 EmpSearch를 전달하도록 수정하였다.
com.oracleclub.study.mvc.dao.EmpDAO.java
...
	/**
	 * 사원목록 정보 조회
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<Emp> selectEmpList(EmpSearch search) {
		return (List<Emp>)getSqlMapClientTemplate().queryForList(NAMESPACE + "selectEmpList", search);
	}

...
 

2.4 EmpDAOTest.java 수정

  • selectEmpList 메소드의 아규먼트가 변경되어 테스트케이스에서 컴파일 오류가 발생한다.
  • 아래와 같이 EmpSearch 객체를 임의로 생성해서 테스트를 다시 해보자
com.oracleclub.study.mvc.dao.EmpDAOTest.java

...
	@Test
	public void testSelectEmpList() {
		EmpSearch search = new EmpSearch();
		search.setDeptno(10);
		Assert.assertTrue(empDAO.selectEmpList(search).size() > 0);
	}
...

2.5 EmpBO.java 수정

  • getEmpList 메소드에서 EmpSearch를 DAO에 전달하도록 수정하였다.
com.oracleclub.study.mvc.bo.EmpBO.java

...

	/**
	 * 사원목록 조회
	 * 
	 * @return
	 */
	public List<Emp> getEmpList(EmpSearch search) {
		return empDAO.selectEmpList(search);
	}

...

2.6 EmpListController.java 수정

  • 검색용 모델객체인 EmpSearch를 @ModelAttribute를 이용하여 jsp로부터 전달받는다.
  • empBO.getEmpList()를 호출할 때 empSearch를 전달한다.
com.oracleclub.study.mvc.controller.EmpListController.java
package com.oracleclub.study.mvc.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.oracleclub.study.mvc.bo.EmpBO;
import com.oracleclub.study.mvc.model.EmpSearch;

/**
 * 사원목록 조회
 * 
 * @author : gurubee
 * 
 */
@Controller
public class EmpListController {

	@Autowired
	private EmpBO empBO;

	@RequestMapping(value = "/emp/list")
	public ModelAndView list(@ModelAttribute EmpSearch empSearch) {

		ModelAndView mv = new ModelAndView();

		// 사원정보 조회 추가
		mv.addObject("empList", empBO.getEmpList(empSearch));

		// View 지정
		// mvc-dispatcher-servlet.xml 파일의 viewResolver를 사용
		mv.setViewName("emp/list");

		return mv;
	}
}

2.7 list.jsp 검색기능 추가

  • 부서번호, 이름, 직업으로 검색할 수 있는 콤보박스, 텍스트박스를 추가하였다.
/WEB-INF/pages/emp/list.jsp
<%@ page language="java" contentType="text/html;charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ko">
<head>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8">
<style>
.error {
    color: #ff0000;
}
.errorblock{
    color: #000;
    background-color: #ffEEEE;
    border: 3px solid #ff0000;
    padding:8px;
    margin:16px;
}
</style>
<script type="text/javascript" language="JavaScript">
    function showMessage(msg){
        if(msg != ''){
            alert(msg); 
        }   
    }

    function runRegisterForm(){        
        location.href = "/emp/form";        
    }

    function runDelete(){
        if(isChecked(document.getElementsByName("empno"))){
            if(confirm('정말 삭제하시겠습니까?')){
                 document.form.action = '/emp/remove';
                 document.form.submit();
            }else{              
                return;
            }           
        }else{
            alert('삭제할 사원을 선택해 주세요!');
        }
    }

    function isChecked(chkbox){
        var flag = false;
        for(var i=0 ; i<chkbox.length ; i++){
            if(chkbox[i].checked){
                flag = true;
                break;
            }   
        }
        return flag;
    }
    
</script>
</head>
<body onload="showMessage('${msg}');">
<form name="sform" method="post" action="/emp/list">
    <table width="50%" border="0">
        <tr>
            <td width="100%" align="right">
            	
            	<select name="deptno" class="combobox">
	                <option value="0" >부서</option>
	                <option value="10" <c:if test="${empSearch.deptno==10}">selected</c:if>>10</option>                 
	                <option value="20" <c:if test="${empSearch.deptno==20}">selected</c:if>>20</option> 
	                <option value="30" <c:if test="${empSearch.deptno==30}">selected</c:if>>30</option>
	            </select>
	            
	            <select name="searchKey" class="combobox">
	                <option value="ename" <c:if test="${empSearch.searchKey=='ename'}">selected</c:if>>이름</option>
	                <option value="job"  <c:if test="${empSearch.searchKey=='job'}">selected</c:if>>직업</option> 
	            </select>

                <input type="text" name="searchValue" value="${empSearch.searchValue}" class="txtbox" size="25" />
                <input type="submit" value="검색" />  
                
                <input type="button" value="등록" onclick="runRegisterForm();"/>
                <input type="button" value="삭제" onclick="runDelete();"/>
            </td>
        </tr>
    </table>

    <table width="50%" border="1">
        <tr>
            <th>선택</th>
            <th>empno</th>
            <th>ename</th>
            <th>job</th>
            <th>sal</th>
            <th>mgr</th>
            <th>deptno</th>            
        </tr>
        <c:forEach var="emp" items="${empList}" varStatus="c">
            <tr  > 
                <td><input type="radio" name="empno" value="${emp.empno}" /></td>
                <td>${emp.empno}</td>
                <td><a href="/emp/view/${emp.empno}">${emp.ename}</a></td>
                <td>${emp.job}</td>
                <td><fmt:formatNumber value="${emp.sal}" type="number" /></td>
                <td>${emp.mgr}</td>
                <td>${emp.deptno}</td>                
            </tr>
        </c:forEach>
    </table>
</form>
</body>
</html>

2.8 테스트

문서정보

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.