본문 바로가기

학원/복기

[Mybatis] 전달값 표현식 / bind 엘리먼트

전달값을 전달할 때 표현식이 두가지가 존재한다.

#{변수명|필드명|맵키} ['전달값'] 으로 전달되어 전달값을 SQL 명령에서 문자값으로 사용된다.

${변수명|필드명|맵키}[전달값] 으로 전달되어 전달값을 SQL 명령에서 부분 명령으로 사용된다.

 

하지만 $ 표현식은 InSQL 공격에 취약하므로 사용하는 것을 권장하지는 않는다. 

 

예제를 보자.

 

검색대상과 검색단어를 전달받아 HYHEWON 테이블에 저장된 회원정보를 검색대상(컬럼명)에 검색단어(비교값)가 저장된 회원정보를 검색하여, 검색결과를 객체로 제공하는 엘리먼트를 선언해보자. (맵객체를 이용할 것이다)

 

xml 매퍼

 

전달값을 SQL 명령에서 부분 명령으로 사용하기 위해 $ 표현식을 사용한다.

 

[MyhewonMapper.xml]

<select id="selectSearchHewonList" parameterType="map" resultMap="myHewonResultMap">
	select hewon_id, hewon_name, hewon_phone, hewon_email, hewon_status from myhewon
		where ${searchColumn}=${searchKeyword} order by hewon_id
</select>

 

인터페이스 매퍼

public interface MyHewonMapper {
	//...
    	//...
	List<MyHewon> selectSearchHewonList(Map<String, Object> map);
}

 

DAO 

//...
//...
public List<Map<String, Object>> selectSearchHewonList() {
	SqlSession sqlSession=getSqlSessionFactory().openSession(true);
	try {
		return sqlSession.getMapper(MyHewonMapper.class).selectSearchHewonList();
	} finally {
		sqlSession.close();
	}
}

 

JSP 문서로 확인

 

[hewonListSearchSelect.jsp]

<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@page import="xyz.itwill.dto.MyHewon"%>
<%@page import="xyz.itwill.dao.MyHewonDAO"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	request.setCharacterEncoding("utf-8");

	String searchColumn=request.getParameter("searchColumn");
	String searchKeyword=request.getParameter("searchKeyword");

	List<MyHewon> hewonList=null;
	
	if(searchKeyword==null || searchKeyword.equals("")) {
		hewonList=MyHewonDAO.getDAO().selectHewonList();//전체 검색
	} else {
		Map<String, Object> map=new HashMap<>();
		map.put("searchColumn", searchColumn);
		map.put("searchKeyword", searchKeyword);
		
		hewonList=MyHewonDAO.getDAO().selectSearchHewonList(map);//조건 검색
	}
%>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
	border: 1px solid black;
	border-collapse: collapse;
}

td {
	border: 1px solid black;
	text-align: center;
	padding: 3px;
}

.id { width: 150px; }
.name { width: 150px; }
.phone { width: 200px; }
.email { width: 200px; }
.status { width: 100px; }
</style>
</head>
<body>
	<h1>회원목록</h1>
	<hr>
	<table>
		<tr>
			<td class="id">아이디</td>
			<td class="name">이름</td>
			<td class="phone">전화번호</td>
			<td class="email">이메일</td>
			<td class="status">공개범위</td>
		</tr>
		<% if(hewonList.isEmpty()) { %>
			<tr>
				<td colspan="5">검색된 회원정보가 없습니다.</td>
			</tr>
		<% } else { %>
			<% for(MyHewon hewon : hewonList) { %>
			<tr>
				<td><%=hewon.getId() %></td>
				<td><%=hewon.getName() %></td>
				<td><%=hewon.getPhone() %></td>
				<td><%=hewon.getEmail() %></td>
				<td><%=hewon.getStatus() %></td>
			</tr>
			<% } %>
		<% } %>
	</table>
	<br>
	
	<form method="post">
		<%-- 검색대상 입력(선택) : 전달값을 반드시 테이블의 컬럼명과 같도록 작성 --%>
		<select name="searchColumn">
			<option value="hewon_id" selected="selected">아이디</option>
			<option value="hewon_name">이름</option>
			<option value="hewon_phone">전화번호</option>
			<option value="hewon_email">이메일</option>
		</select>
		<%-- 검색단어 입력 --%>
		<input type="text" name="searchKeyword">
		<button type="submit">검색</button>
	</form>	
</body>
</html>

 

 

bind 엘리먼트

 

이번에는 검색단어가 포함된 정보를 검색하는 엘리먼트를 작성해보자

 

검색대상과 검색단어를 전달받아 HYHEWON 테이블에 저장된 회원정보를 검색대상(컬럼명)에 검색단어(비교값)가 포함된 회원정보를 검색하여 검색결과를 객체로 제공하는 엘리먼트를 선언할 것이다.

 

xml 매퍼

 

<select id="selectSearchHewonList" parameterType="map" resultMap="myHewonResultMap">
	select hewon_id, hewon_name, hewon_phone, hewon_email, hewon_status from myhewon 
		where ${searchColumn} like '%'||#{searchKeyword}||'%' order by hewon_id
</select>

 

이를 bind 엘리먼트를 사용해서 다시 작성해보자

 

bind는 SQL 명령에서 사용하기 위한 값을 제공하는 엘리먼트이다.

일반적으로 bind는 parameterType 속성값으로 전달받은 값을 변경하여 SQL 명령에서 사용할 목적으로 사용한다.

bind 엘리먼트로 제공된 값은 SQL 명령에서 #{이름} 형식으로 표현하여 사용할 수 있다. 

 

 - name 속성 : SQL 명령에서 사용할 이름을 속성값으로 설정한다.

 - value 속성 : SQL 명령에서 사용할 값을 속성값으로 설정한다.

    → parameterType 속성값으로 전달받은 값에 문자열을 결합할 경우 + 연산자를 사용한다.

 

<select id="selectSearchHewonList" parameterType="map" resultMap="myHewonResultMap">
	<bind name="keyword" value="'%'+searchKeyword+'%'"/>
	select hewon_id, hewon_name, hewon_phone, hewon_email, hewon_status from myhewon 
		where ${searchColumn} like #{keyword} order by hewon_id
</select>

 

 


이번엔 이름을 전달받아 MYHEWON 테이블에 저장된 해당 이름의 회원정보를 검색하여 검색결과를 객체로 제공하는 엘리먼트를 선언해보자

 

 

xml 매퍼에 엘리먼트 선언 

<select id="selectNameHewonList" parameterType="string" resultMap="myHewonMapper"> 
	select hewon_id, hewon_name, hewon_phone, hewon_email, hewon_status from myhewon 
		where hewon_name like #{name} order by hewon_id
</select>

 

인터페이스 매퍼 파일에 추상메소드 추가

public interface MyHewonMapper {
	//...
    	//...
	List<MyHewon> selectNameHewonList(String name);
}

 

DAO 클래스에 메소드 선언

public class MyHewonDAO extends AbstractSession {
	private static MyHewonDAO _dao;

	private MyHewonDAO() {
		// TODO Auto-generated constructor stub
	}
	
	static {
		_dao=new MyHewonDAO();
	}
	
	public static MyHewonDAO getDAO() {
		return _dao;
	}
	
	//...
    	//...
	
	public List<MyHewon> selectNameHewonList(String name) {
		SqlSession sqlSession=getSqlSessionFactory().openSession(true);
		try {
			return sqlSession.getMapper(MyHewonMapper.class).selectNameHewonList(name);
		} finally {
			sqlSession.close();
		}
}

 

 

JSP 문서

 

[hewonListNameSearchSelect.jsp]

<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@page import="xyz.itwill.dto.MyHewon"%>
<%@page import="xyz.itwill.dao.MyHewonDAO"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	request.setCharacterEncoding("utf-8");

	String name=request.getParameter("name");

	List<MyHewon> hewonList=null;
	
	if(name==null || name.equals("")) {//전달값이 없는 경우
		hewonList=MyHewonDAO.getDAO().selectHewonList();//전체 검색
	} else {
		hewonList=MyHewonDAO.getDAO().selectNameHewonList(name);//조건 검색
	}
%>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
	border: 1px solid black;
	border-collapse: collapse;
}

td {
	border: 1px solid black;
	text-align: center;
	padding: 3px;
}

.id { width: 150px; }
.name { width: 150px; }
.phone { width: 200px; }
.email { width: 200px; }
.status { width: 100px; }
</style>
</head>
<body>
	<h1>회원목록</h1>
	<hr>
	<table>
		<tr>
			<td class="id">아이디</td>
			<td class="name">이름</td>
			<td class="phone">전화번호</td>
			<td class="email">이메일</td>
			<td class="status">공개범위</td>
		</tr>
		<% if(hewonList.isEmpty()) { %>
			<tr>
				<td colspan="5">검색된 회원정보가 없습니다.</td>
			</tr>
		<% } else { %>
			<% for(MyHewon hewon : hewonList) { %>
			<tr>
				<td><%=hewon.getId() %></td>
				<td><%=hewon.getName() %></td>
				<td><%=hewon.getPhone() %></td>
				<td><%=hewon.getEmail() %></td>
				<td><%=hewon.getStatus() %></td>
			</tr>
			<% } %>
		<% } %>
	</table>
	<br>
	
	<form method="post">
		이름 : <input type="text" name="name">
		<button type="submit">검색</button>
	</form>	
</body>
</html>