MyBatis : JOIN, IN
MyBatis에서 JOIN과 IN을 어떻게 사용하는지 간단한 예제로 한 번 구현해 보자.
아래처럼 직원들의 이름과 체크박스가 나오고,
원하는 직원을 선택하여 전송버튼을 누르면 선택한 직원의 정보를 출력하는 애플리케이션이다.
1. EmpVO와 DeptVO와 같은 데이터형을 세팅한다.
EmpVO.java (Class)
부서 정보를 JOIN하여 함께 가져올 것이므로!
EmpVO 내에 DeptVO의 객체를 매개변수(포함 클래스)로 선언한다.
package doodoo.dao;
import java.util.*;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class EmpVO {
private int empno, mgr, comm, sal, deptno;
private String ename, job;
private Date hiredate;
private DeptVO dvo = new DeptVO(); //JOIN을 위해 포함 클래스를 선언
}
DeptVO.java (Class)
package doodoo.dao;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class DeptVO {
private int deptno;
private String dname, loc;
}
2. mapper를 작성한다!
우선 JOIN된 컬럼별로 어떤 property에 배정할 것인지 지정해 준다.
resultMap은 column명과 변수명이 다를 때 많이 사용된다. 직접 세팅해줘야 하니까...
<resultMap type="doodoo.dao.EmpVO" id="empMap">
<!-- resultMap??? -->
<!-- property = setter를 찾아 주고 column의 값을 넣어준다. -->
<!-- vo.getDvo().setDname(rs.getString("dname")) -->
<result property="dvo.dname" column="dname"/> <!-- dvo의 dname을 잡아 준다. -->
<!-- vo.getDvo().setLoc(rs.getString("loc")) -->
<result property="dvo.loc" column="loc"/>
</resultMap>
그리고 기본적인 쿼리문들을 작성한다.
이 때, 반복적으로 사용되는 SQL문장은 따로 id만 부여하여 작성한 후!
필요한 위치에서 <include> 태그를 이용해 여러 SQL문에서 다양하게 활용할 수 있도록 세팅한다.
emp-mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="doodoo.mapper.emp-mapper">
<resultMap type="doodoo.dao.EmpVO" id="empMap">
<result property="dvo.dname" column="dname"/>
<result property="dvo.loc" column="loc"/>
</resultMap>
<!-- 반복적인 SQL문장이 있을 때 주로 사용한다. (JOIN ,SUBQUERY 등...) -->
<sql id="join-sql">
SELECT empno, ename, job, hiredate, sal, emp.deptno, dname, loc
FROM emp, dept
WHERE emp.deptno = dept.deptno
</sql>
<select id="empDeptJoinData" resultMap="empMap">
<include refid="join-sql"/>
</select>
<select id="empDeptDetailData" resultMap="empMap" parameterType="int">
<include refid="join-sql"/>
AND empno=#{empno}
</select>
<select id="empGetEnameData" resultType="String">
SELECT ename FROM emp
</select>
</mapper>
동적 쿼리
: 사용자가 보내는 값이 계속 달라질 때, 그 가변값에 대응할 수 있는 쿼리를 의미한다.
<trim> 태그를 이용해서 구현할 수 있다.
<!-- 반복적인 SQL문장이 있을 때 주로 사용한다. (JOIN ,SUBQUERY 등...) -->
<sql id="join-sql">
SELECT empno, ename, job, hiredate, sal, emp.deptno, dname, loc
FROM emp, dept
WHERE emp.deptno = dept.deptno
</sql>
<!-- 동적 쿼리 : 사용자가 보내는 값들이 계속 달라질 때 -->
<select id="empFindData" resultMap="empMap" parameterType="hashmap">
<include refid="join-sql"/>
AND ename
<trim prefix="IN">
<foreach collection="nameArr" item="name" open="(" close=")" separator=",">#{name}</foreach>
</trim>
</select>
<trim prefix="IN">
→ IN을 맨 앞에 붙여 다음 동적 쿼리를 생성하겠다.
<foreach collection="nameArr" item="name" open="(" close=")" separator=","> #{name} </foreach>
→ String[] nameArr = {"name1","name2","name3",..}; 이 있다고 했을 때,
('#{name}','#{name}','#{name}',...)를 만들어 준다.
3. Config.xml 에 VO랑 mapper를 등록하여 톰캣이 읽어 사용할 수 있게 해준다.
Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias type="doodoo.dao.EmpVO" alias="EmpVO"/>
<typeAlias type="doodoo.dao.DeptVO" alias="DeptVO"/>
</typeAliases>
<environments default="development"> <!-- 개발환경 만들기 -->
<environment id="development">
<transactionManager type="JDBC"/> <!-- AutoCommit을 쓰겠다. -->
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
<property name="username" value="username"/>
<property name="password" value="pwd"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="doodoo/dao/emp-mapper.xml"/>
</mappers>
</configuration>
4. Config.xml을 읽어와 SqlSession을 생성하고 mapper의 각 SQL문에 맞는 메서드를 구현한다.
EmpDAO.java
package doodoo.dao;
import java.io.Reader;
import java.util.*;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class EmpDAO {
private static SqlSessionFactory ssf;
static {
try {
Reader reader = Resources.getResourceAsReader("Config.xml");
ssf = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static List < EmpVO > empDeptJoinData() {
SqlSession session = ssf.openSession();
List < EmpVO > list = session.selectList("empDeptJoinData");
session.close();
return list;
}
public static EmpVO empDeptDetailData(int empno) {
SqlSession session = ssf.openSession();
EmpVO vo = session.selectOne("empDeptDetailData", empno);
session.close();
return vo;
}
public static List < String > empGetEnameData() {
SqlSession session = ssf.openSession();
List < String > list = session.selectList("empGetEnameData");
session.close();
return list;
}
public static List < EmpVO > empFindData(Map map) {
SqlSession session = ssf.openSession();
List < EmpVO > list = session.selectList("empFindData", map);
session.close();
return list;
}
}
5. JSP로 화면을 구현하면 끝!
find.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="doodoo.dao.*, java.util.*"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
EmpDAO dao = new EmpDAO();
List<String> list = dao.empGetEnameData();
request.setAttribute("list",list);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<style type="text/css">
.container{
margin-top: 50px;
}
.row{
margin: 0px auto;
width: 350px;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<form method="post" action="find_ok.jsp">
<c:forEach var="name" items="${list }">
<input type="checkbox" name=names value="${name }">${name }<br>
</c:forEach>
<br>
<input type=submit value="전송" class="btn btn-sm btn-primary">
</form>
</div>
</div>
</body>
</html>
find_ok.jsp
find.jsp에서 넘겨 준 names를 어떻게 받아 처리하는지!
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="doodoo.dao.*, java.util.*"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String[] names = request.getParameterValues("names");
if(names!=null && names.length>0){
Map map = new HashMap();
map.put("nameArr", names);
EmpDAO dao = new EmpDAO();
List<EmpVO> list = dao.empFindData(map);
request.setAttribute("list", list);
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<style type="text/css">
.container{
margin-top: 50px;
}
.row{
margin: 0px auto;
width: 700px;
}
</style>
</head>
<body>
<div class="container">
<h1 class="text-center">사원 목록</h1>
<div class="row">
<table class="table table-hover">
<tr class="danger">
<th class="text-center">사번</th>
<th class="text-center">이름</th>
<th class="text-center">직위</th>
<th class="text-center">입사일</th>
<th class="text-center">급여</th>
<th class="text-center">부서명</th>
<th class="text-center">근무지</th>
</tr>
<c:forEach var="vo" items="${list }">
<tr>
<td class="text-center">${vo.empno }</td>
<td class="text-center"><a href="detail.jsp?empno=${vo.empno}">${vo.ename }</a></td>
<td class="text-center">${vo.job }</td>
<td class="text-center">${vo.hiredate }</td>
<td class="text-center">${vo.sal }</td>
<td class="text-center">${vo.dvo.dname }</td><!-- vo.getDvo().getDname() -->
<td class="text-center">${vo.dvo.loc }</td>
</tr>
</c:forEach>
</table>
</div>
</div>
</body>
</html>
'부트캠프(END) > Oracle' 카테고리의 다른 글
regexp - 수정중 (0) | 2022.08.18 |
---|---|
PL/SQL : TRIGGER (0) | 2022.07.07 |
PL/SQL : PROCEDURE (0) | 2022.07.06 |