Java EE 정리 28
05 Apr 2019
Reading time ~9 minutes
Java EE 정리 28 - MyBatis(3)
컬럼 여러개 레코드 여러개 조회할 때
- 입력되는 (parameterType) 부서번호에 따른 사원정보 조회(resultType)
- 입력되는 값이 단일형이라면 자바 데이터형 사용
- 노드안에서 사용할 때에는 #{ 아무값 }
- 입력되는 값이 복합형이라면 VO를 사용
- 이 때는 반드시 #{ getter명 } , ${ getter 명 }을 사용
- #은 바인드변수로 바뀜, $는 쿼리로 바뀜
- 문자열일 때 바인드변수므로 작은 따옴표 안붙여도 됨
- 문자열일 때 $라면 작은 따옴표를 사용해야 한다.
- 입력되는 값이 단일형이라면 자바 데이터형 사용
<!-- exam_mapper1.xml -->
...
<!-- 컬럼 여러개 레코드 여러개 조회할 때 -->
<select id="multiColumnRow" resultType="kr.co.sist.exam.domain.Emp" parameterType="int">
SELECT empno, ename, job, sal, mgr, TO_CHAR(hiredate,'yyyy-mm-dd q') hiredate
FROM emp
WHERE deptno = #{ deptno }
</select>
...
package kr.co.sist.exam.domain;
public class Emp {
private int empno, sal, mgr;
private String ename, job, hiredate;
// getter, setter 생성
...
// MyBatisDAO
...
public List<Emp> multiColumnRow(int deptno) {
List<Emp> list = null;
// 4. MyBatis Handler 얻기
SqlSession ss = getSessionFactory().openSession();
// 5. mapper에서 쿼리가 존재하는 id 찾아 실행
list = ss.selectList("multiColumnRow", deptno);
ss.close();
return list;
}
...
// MyBatisService
...
public List<Emp> multiColumnRow(int deptno) {
List<Emp> list = null;
MyBatisDAO mb_dao = MyBatisDAO.getInstance();
list = mb_dao.multiColumnRow(deptno);
return list;
}
...
- 페이지가 유지되도록 hidden 태그를 추가해서 page param을 전달
<!-- multi_column_row.jsp -->
...
<%
MyBatisService mbs = new MyBatisService();
List<Integer> deptnoList = mbs.multiRow();
pageContext.setAttribute("deptnoList", deptnoList);
String deptno = request.getParameter("deptno");
if(deptno != null) {
List<Emp> empList = mbs.multiColumnRow(Integer.parseInt(deptno));
pageContext.setAttribute("empList", empList);
}
%>
<form name="frm" action="main.jsp">
<label>부서번호</label>
<select name="deptno">
<c:forEach var="deptno" items="${ deptnoList }">
<option value="${ deptno }"><c:out value="${ deptno }" escapeXml="false"/></option>
</c:forEach>
</select>
<input type="hidden" name="page" value="date0405/multi_column_row"/>
<input type="submit" value="부서별 사원조회" class="btn"/>
</form>
<div>
<c:if test="${ not empty param.deptno }">
<table border="1">
<tr>
<th width="40">번호</th>
<th width="80">사원번호</th>
<th width="120">사원명</th>
<th width="80">매니저번호</th>
<th width="80">연봉</th>
<th width="150">입사일</th>
<th width="100">직무</th>
</tr>
<c:if test="${ empty empList }">
<tr>
<td colspan="7" align="center">
<strong>${ param.deptno }</strong>번 부서에는 사원이 존재하지 않습니다.
</td>
</tr>
</c:if>
<c:forEach var="emp" items="${ empList }">
<c:set var="i" value="${ i+1 }"/>
<tr>
<td><c:out value="${ i }"/></td>
<td><c:out value="${ emp.empno }"/></td>
<td><c:out value="${ emp.ename }"/></td>
<td><c:out value="${ emp.mgr }"/></td>
<td><c:out value="${ emp.sal }"/></td>
<td><c:out value="${ emp.hiredate }"/></td>
<td><c:out value="${ emp.job }"/></td>
</tr>
</c:forEach>
</table>
</c:if>
</div>
resultMap 노드
- resultMap
- 조회하는 컬럼과 Domain의 setter를 미리 mapping시키는 일을 함
- 조회결과를 미리 매핑한 resultMap노드를 선언했다면 select노드에서에서 resultMap 속성을 사용
<!-- mapper.xml -->
...
<mapper namespace="kr.co.sist.exam1">
<resultMap id="mapId" type="패키지명.Domain명">
<result column="컬럼명" property="setter명"/>
...
</resultMap>
...
<select id="아이디" parameterMap="Map" parameterType="기본형" resultMap="mapId">
...
</selecT>
...
- 컬럼명은 대소문자 구분하지 않음, setter는 대소문자 구분
<!-- exam_mapper1.xml -->
...
<mapper namespace="kr.co.sist.exam1">
<!-- Emp Domain을 resultMap으로 설정 -->
<resultMap type="kr.co.sist.exam.domain.Emp" id="empResult">
<result column="empno" property="empno"/>
<result column="ENAME" property="ename"/>
<result column="job" property="job"/>
<result column="sal" property="sal"/>
<result column="hiredate" property="hiredate"/>
<result column="MGR" property="mgr"/>
</resultMap>
...
<select id="multiColumnRow" resultMap="empResult" parameterType="int">
SELECT empno, ename, job, sal, mgr, TO_CHAR(hiredate,'yyyy-mm-dd q') hiredate
FROM emp
WHERE deptno = #{ deptno }
</select>
...
WHERE의 값이 여러개인 경우
- parameterType에 VO를 설정하고 #{ getter명 }, ${ getter명 } 을 사용한다.
- 입력되는(parameterType) 부서번호와 직무에 해당하는 사원 정보를 조회(resultType)
<!-- exam_mapper1.xml -->
...
<!-- 조회 컬럼이 여러개인 경우 -->
<select id="multiparam" parameterType="kr.co.sist.exam.vo.EmpVO" resultMap="empResult">
SELECT empno, ename, job, sal, mgr, TO_CHAR(hiredate,'yyyy-mm-dd q') hiredate
FROM emp
WHERE deptno = #{ deptno } and job=#{ job }
</select>
...
package kr.co.sist.exam.vo;
public class EmpVO {
private int deptno;
private String job;
// 인자있는 생성자, getter, setter 생성
...
public class MyBatisDAO1 {
public List<Emp> multiParam(EmpVO ev) {
List<Emp> list = null;
// 4. 핸들러 얻기
SqlSession ss = MyBatisDAO.getInstance().getSessionFactory().openSession();
list = ss.selectList("multiparam", ev);
ss.close();
return list;
}
}
public class MyBatisService1 {
public List<Emp> multiParam(EmpVO ev) {
List<Emp> list = null;
MyBatisDAO1 mb_dao1 = new MyBatisDAO1();
list = mb_dao1.multiParam(ev);
return list;
}
}
<!-- multi_param.jsp -->
...
<%
String deptno = request.getParameter("deptno");
String job = request.getParameter("job");
if(deptno != null && job != null) {
MyBatisService1 mbs = new MyBatisService1();
EmpVO ev = new EmpVO(Integer.parseInt(deptno), job);
List<Emp> empList = mbs.multiParam(ev);
pageContext.setAttribute("empList", empList);
}
%>
<form name="frm" action="main.jsp">
<label>부서번호</label>
<c:set var="deptno" value="10,20,30,40"/>
<c:forTokens items="${ deptno }" delims="," var="deptno">
<input type="radio" name="deptno" value="${ deptno }"/>
<c:out value="${ deptno }" escapeXml="false"/>
</c:forTokens>
<br/>
<label>직무</label>
<c:set var="job" value="ANALYST,CLERK,MANAGER,SALESMAN,PRESIDENT"/>
<c:forTokens items="${ job }" delims="," var="job">
<input type="radio" name="job" value="${ job}"/>
<c:out value="${ job }" escapeXml="false"/>
</c:forTokens>
<input type="hidden" name="page" value="date0405/multi_param"/><br/>
<input type="submit" value="부서별 사원조회" class="btn"/>
</form>
<div>
<c:if test="${ not empty param.deptno }">
<table border="1">
<tr>
<th width="40">번호</th>
<th width="80">사원번호</th>
<th width="120">사원명</th>
<th width="80">매니저번호</th>
<th width="80">연봉</th>
<th width="150">입사일</th>
<th width="100">직무</th>
</tr>
<c:if test="${ empty empList }">
<tr>
<td colspan="7" align="center">
<strong>${ param.deptno }</strong>번 부서에는 사원이 존재하지 않습니다.
</td>
</tr>
</c:if>
<c:forEach var="emp" items="${ empList }">
<c:set var="i" value="${ i+1 }"/>
<tr>
<td><c:out value="${ i }"/></td>
<td><c:out value="${ emp.empno }"/></td>
<td><c:out value="${ emp.ename }"/></td>
<td><c:out value="${ emp.mgr }"/></td>
<td><c:out value="${ emp.sal }"/></td>
<td><c:out value="${ emp.hiredate }"/></td>
<td><c:out value="${ emp.job }"/></td>
</tr>
</c:forEach>
</table>
</c:if>
</div>
- 선택한 라디오 버튼이 유지되도록 만들기
...
<label>부서번호</label>
<c:set var="deptno" value="10,20,30,40"/>
<c:forTokens items="${ deptno }" delims="," var="deptno">
<input type="radio" name="deptno" value="${ deptno }" ${ deptno eq param.deptno ? "checked='checked'" : "" }/>
<c:out value="${ deptno }" escapeXml="false"/>
</c:forTokens>
<br/>
<label>직무</label>
<c:set var="job" value="ANALYST,CLERK,MANAGER,SALESMAN,PRESIDENT"/>
<c:forTokens items="${ job }" delims="," var="job">
<input type="radio" name="job" value="${ job}" ${ job eq param.job ? "checked='checked'" : "" }/>
<c:out value="${ job }" escapeXml="false"/>
</c:forTokens>
...
SQL 노드
- 중복사용되는 쿼리를 sql노드에 설정하고
<sql id="아이디">
중복 쿼리
</sql>
- 사용될 때 include해서 사용
<include refid="아이디"/>
- SQL 노드 사용 예
- 중복 쿼리가 존재
...
<select id="multiColumnRow" resultMap="empResult" parameterType="int">
SELECT empno, ename, job, sal, mgr, TO_CHAR(hiredate,'yyyy-mm-dd q') hiredate
FROM emp
WHERE deptno = #{ deptno }
</select>
<select id="multiparam" parameterType="kr.co.sist.exam.vo.EmpVO" resultMap="empResult">
SELECT empno, ename, job, sal, mgr, TO_CHAR(hiredate,'yyyy-mm-dd q') hiredate
FROM emp
WHERE deptno = #{ deptno } and job=#{ job }
</select>
...
...
<!-- sql 노드를 사용해서 중복 쿼리를 줄임 -->
<sql id="empDup">
SELECT empno, ename, job, sal, mgr, TO_CHAR(hiredate,'yyyy-mm-dd q') hiredate
FROM emp
</sql>
...
<select id="multiColumnRow" resultMap="empResult" parameterType="int">
<include refid="empDup"/>
WHERE deptno = #{ deptno }
</select>
<select id="multiparam" parameterType="kr.co.sist.exam.vo.EmpVO" resultMap="empResult">
<include refid="empDup"/>
WHERE deptno = #{ deptno } and job=#{ job }
</select>
...
<의 조회
- 사원테이블에서 입력된 연봉보다 적게 받는 사원의 사원 번호, 사원명, 직무, 매니저번호, 입사일을 조회
- ’<’는 직접 사용할 수 없다.
- ‘<’을 사용.
<!-- exam_mapper1.xml -->
...
<!-- < 의 조회 -->
<select id="lessThan" resultMap="empResult" parameterType="Integer">
<include refid="empDup"/>
WHERE sal < #{ sal }
</select>
...
- ’<’를 직접 사용하고 싶다면 CDATA Section을 사용한다.
- CDATA Section 사이는 노드가 아닌 단순한 문자열임을 알려주는 것
<![CDATA[
CDATA Section
]]>
...
<select id="lessThan" resultMap="empResult" parameterType="Integer">
<include refid="empDup"/>
<![CDATA[
WHERE sal < #{ sal }
]]>
</select>
...
// MyBatisDAO1
...
public List<Emp> lessThan(int sal) {
List<Emp> list = null;
SqlSession ss = MyBatisDAO.getInstance().getSessionFactory().openSession();
list = ss.selectList("lessThan",sal);
ss.close();
return list;
}
...
// MyBatisService1
...
public List<Emp> lessThan(int sal) {
List<Emp> list = null;
if (sal < 0) { // 음수는 절대값 처리
sal = Math.abs(sal);
// 또는 sal = -sal;
}
MyBatisDAO1 mb_dao1 = new MyBatisDAO1();
list = mb_dao1.lessThan(sal);
return list;
}
}
<!-- main_menu.jsp -->
...
<li><a href="main.jsp?page=date0405/less_than"><의 비교</a></li>
...
<!-- less_than.jsp -->
<%
MyBatisService1 mbs = new MyBatisService1();
String sal = request.getParameter("sal");
if(sal != null) {
List<Emp> list = mbs.lessThan(Integer.parseInt(sal));
pageContext.setAttribute("empList", list);
}
%>
<form name="frm" action="main.jsp">
<label>연봉</label>
<input type="text" name="sal" class="inputBox"/>
<input type="hidden" name="page" value="date0405/less_than"/>
<input type="submit" value="사원조회" class="btn"/>
</form>
<div>
<c:if test="${ not empty param.sal }">
<div>
${ param.sal } 보다 연봉을 적게 받는 사원 정보
</div>
<table border="1">
<tr>
<th width="40">번호</th>
<th width="80">사원번호</th>
<th width="120">사원명</th>
<th width="80">매니저번호</th>
<th width="80">연봉</th>
<th width="150">입사일</th>
<th width="100">직무</th>
</tr>
<c:if test="${ empty empList }">
<tr>
<td colspan="7" align="center">
<strong>${ param.sal }</strong>보다 적게 받는 사원은 존재하지 않습니다.
</td>
</tr>
</c:if>
<c:forEach var="emp" items="${ empList }">
<c:set var="i" value="${ i+1 }"/>
<tr>
<td><c:out value="${ i }"/></td>
<td><c:out value="${ emp.empno }"/></td>
<td><c:out value="${ emp.ename }"/></td>
<td><c:out value="${ emp.mgr }"/></td>
<td><c:out value="${ emp.sal }"/></td>
<td><c:out value="${ emp.hiredate }"/></td>
<td><c:out value="${ emp.job }"/></td>
</tr>
</c:forEach>
</table>
</c:if>
</div>
> 의 조회
- ’>’는 ‘<’와 다르게 에러가 안난다.
- >도 사용 가능하다.
- 사원테이블에서 입력된 연봉보다 많이 받는 사원의 empno, ename, job, sal, mgr, hiredate 조회
<!-- exam_mapper1.xml -->
...
<!-- > 의 조회 -->
<select id="greaterThan" resultMap="empResult" parameterType="Integer">
<include refid="empDup"/>
WHERE sal > #{ sal }
</select>
...
// MyBatisDAO1
...
public List<Emp> greaterThan(int sal) {
List<Emp> list = null;
SqlSession ss = MyBatisDAO.getInstance().getSessionFactory().openSession();
list = ss.selectList("greaterThan",sal);
ss.close();
return list;
}
...
// MyBatisService1
...
public List<Emp> greaterThan(int sal) {
List<Emp> list = null;
if (sal < 0) { // 음수는 절대값 처리
sal = Math.abs(sal);
// 또는 sal = -sal;
}
MyBatisDAO1 mb_dao1 = new MyBatisDAO1();
list = mb_dao1.greaterThan(sal);
return list;
}
}
<!-- main_menu.jsp -->
...
<li><a href="main.jsp?page=date0405/greater_than">>의 비교</a></li>
...
<!-- greater_than.jsp -->
...
<%
MyBatisService1 mbs = new MyBatisService1();
String sal = request.getParameter("sal");
if(sal != null) {
List<Emp> list = mbs.greaterThan(Integer.parseInt(sal));
pageContext.setAttribute("empList", list);
}
%>
<form name="frm" action="main.jsp">
<label>연봉</label>
<input type="text" name="sal" class="inputBox"/>
<input type="hidden" name="page" value="date0405/greater_than"/>
<input type="submit" value="사원조회" class="btn"/>
</form>
<div>
<c:if test="${ not empty param.sal }">
<div>
${ param.sal } 보다 연봉을 많이 받는 사원 정보
</div>
<table border="1">
<tr>
<th width="40">번호</th>
<th width="80">사원번호</th>
<th width="120">사원명</th>
<th width="80">매니저번호</th>
<th width="80">연봉</th>
<th width="150">입사일</th>
<th width="100">직무</th>
</tr>
<c:if test="${ empty empList }">
<tr>
<td colspan="7" align="center">
<strong>${ param.sal }</strong>보다 적게 받는 사원은 존재하지 않습니다.
</td>
</tr>
</c:if>
<c:forEach var="emp" items="${ empList }">
<c:set var="i" value="${ i+1 }"/>
<tr>
<td><c:out value="${ i }"/></td>
<td><c:out value="${ emp.empno }"/></td>
<td><c:out value="${ emp.ename }"/></td>
<td><c:out value="${ emp.mgr }"/></td>
<td><c:out value="${ emp.sal }"/></td>
<td><c:out value="${ emp.hiredate }"/></td>
<td><c:out value="${ emp.job }"/></td>
</tr>
</c:forEach>
</table>
</c:if>
</div>
LIKE 의 조회
- 우편번호 검색
- 동을 입력받아(parameterType) 우편번호, 시도, 구군, 동, 번지를 조회(resultType 또는 resultMap)
package kr.co.sist.exam.domain;
public class Zipcode {
private String zipcode, sido, gugun, dong, bunji;
// getter, setter
...
<!-- exam_mapper1.xml -->
...
<!-- Zipcode Domain을 컬럼과 매핑 -->
<resultMap id="zipcodeResult" type="kr.co.sist.exam.domain.Zipcode">
<result column="zipcode" property="zipcode"/>
<result column="sido" property="sido"/>
<result column="gugun" property="gugun"/>
<result column="dong" property="dong"/>
<result column="bunji" property="bunji"/>
</resultMap>
...
<!-- LIKE 의 조회 -->
<select id="like" resultMap="zipcodeResult" parameterType="String">
SELECT zipcode, sido, gugun, dong, NVL(bunji, ' ') bunji
FROM zipcode
where dong LIKE '%'||#{ dong }||'%'
</select>
...
// MyBatisDAO1
...
public List<Zipcode> like(String dong) {
List<Zipcode> list = null;
SqlSession ss = MyBatisDAO.getInstance().getSessionFactory().openSession();
list = ss.selectList("like", dong);
ss.close();
return list;
}
...
// MyBatisService1
...
public List<Zipcode> like(String dong) {
List<Zipcode> list = null;
MyBatisDAO1 mb_dao1 = new MyBatisDAO1();
list = mb_dao1.like(dong);
return list;
}
...
<!-- main_menu.jsp -->
...
<li><a href="main.jsp?page=date0405/like">LIKE의 조회</a></li>
...
<!-- like.jsp -->
<%
MyBatisService1 mbs = new MyBatisService1();
String dong = request.getParameter("dong");
if(dong != null) {
List<Zipcode> list = mbs.like(dong);
pageContext.setAttribute("addrList", list);
}
%>
<form name="frm" action="main.jsp">
<label>동 이름</label>
<input type="text" name="dong" class="inputBox"/>
<input type="hidden" name="page" value="date0405/like"/>
<input type="submit" value="검색" class="btn"/>
</form>
<div>
<c:if test="${ not empty param.dong }">
<div>
${ param.dong } 의 조회
</div>
<table border="1">
<tr>
<th width="100">우편번호</th>
<th width="400">주소</th>
</tr>
<c:if test="${ empty addrList }">
<tr>
<td colspan="7" align="center">
<strong>${ param.dong }</strong>은 존재하지 않습니다.
</td>
</tr>
</c:if>
<c:forEach var="addr" items="${ addrList }">
<tr>
<td>
<c:out value="${ addr.zipcode }"/>
</td>
<td>
<c:out value="${ addr.sido } ${ addr.gugun } ${ addr.dong } ${ addr.bunji }"/>
</td>
</tr>
</c:forEach>
</table>
</c:if>
</div>