본문 바로가기

학원/복기

[MyBatis] 인터페이스 기반의 매퍼 파일만 사용해 매퍼 등록하기

mybatis 프레임워크에서는 Interface 기반의 매퍼 파일만 사용하여 매퍼를 등록하는 것도 가능하다.

매퍼를 등록하기 위해서는 인터페이스의 추상메소드에 매퍼 어노테이션을 사용하여 SQL 명령을 등록하면 된다.

추상메소드에 등록된 SELECT 명령은 기본적으로 검색행을 자동 매핑하여 객체로 제공한다.
→ 자동 매핑 기능을 사용하여 검색행을 객체로 생성하기 위해 검색행의 컬럼명과 객체를 생성할 클래스의 필드명을 동일하게 작성해야 한다.
→ 검색행의 컬럼명과 클래스의 필드명이 하나도 같지 않은 경우 객체 대신 NULL을 제공한다.

@Results 
: 검색행을 객체로 생성하여 제공하기 위한 매핑 정보를 설정하는 어노테이션

@Results은 XML 기반의 매퍼 파일에서 resultMap 엘리먼트와 유사한 기능 제공하는 어노테이션이다.

 - value 속성 : 검색행의 컬럼값을 객체 필드에 저장하기 위한 매핑정보를 제공하는 Result 어노테이션에 여러개 저장된 배열을 속성값으로 설정한다. 
   → 다른 속성이 없는 경우 속성값만 설정 가능하다.

@Result
: 검색행의 컬럼값을 객체 필드에 저장하기 위한 정보를 제공하는 어노테이션

@Result는 XML 기반의 매퍼 파일에서 id 엘리먼트(result 엘리먼트)와 유사한 기능을 제공하는 어노테이션이다.
 - column 속성 : 검색행의 컬럼명(컬럼값)을 속성값으로 설정한다.
 - property 속성 : 검색행의 컬럼값이 저장될 객체의 필드명을 속성값으로 설정한다.

 

@Results 어노테이션의 매핑 정보는 다른 추상메소드에서 재사용할 수 없기 때문에 유지보수의 효율성 감소한다는 단점이 존재한다. 

 

 

MYHEWON 테이블에 대한 인터페이스 매퍼 선언

[MyHewonInterfaceMapper]

package xyz.itwill.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

import xyz.itwill.dto.MyHewon;


public interface MyHewonInterfaceMapper {
	@Results(value = {
		@Result(column = "hewon_id", property = "id")	
		, @Result(column = "hewon_name", property = "name")	
		, @Result(column = "hewon_phone", property = "phone")	
		, @Result(column = "hewon_email", property = "email")	
		, @Result(column = "hewon_status", property = "status")	
	})
	@Select(value = "select * from myhewon order by hewon_id")
	List<MyHewon> selectHewonList();

	//@Results 어노테이션의 매핑 정보를 다른 추상메소드에서 재사용 불가능 - 유지보수의 효율성 감소
	@Results(value = {
		@Result(column = "hewon_id", property = "id")	
		, @Result(column = "hewon_name", property = "name")	
		, @Result(column = "hewon_phone", property = "phone")	
		, @Result(column = "hewon_email", property = "email")	
		, @Result(column = "hewon_status", property = "status")	
	})
	@Select(value = "select * from myhewon where hewon_name=#{name} order by hewon_id")
	List<MyHewon> selectNameHewonList(String name);
}

 

DAO 클래스 선언

 

[MyHewonInterfaceDAO]

package xyz.itwill.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import xyz.itwill.dto.MyHewon;
import xyz.itwill.mapper.MyHewonInterfaceMapper;

public class MyHewonInterfaceDAO extends AbstractSession {
	private static MyHewonInterfaceDAO _dao;

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

 

 

JSP 

[hewonListInterfaceSelect.jsp]

<%@page import="xyz.itwill.dao.MyHewonInterfaceDAO"%>
<%@page import="xyz.itwill.dto.MyHewon"%>
<%@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=MyHewonInterfaceDAO.getDAO().selectHewonList();//전체 검색
	} else {
		hewonList=MyHewonInterfaceDAO.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>

 

 

 


인터페이스에서 동적 SQL 사용하기

 

@SelectProvider

: SQL 명령을 생성하여 반환하는 클래스(*SQL Buider)의 메소드를 호출하여 SELECT 명령을 반환받아 등록하는 어노테이션

*SQL Builder 클래스 : SQL 객체의 메소드를 호출하여 SQL 명령을 작성하고 SQL 객체에 저장된 SQL 명령을 반환하는 기능을 제공하는 클래스

 

@Selectprovider 어노테이션은 Interface 기반의 매퍼 파일에서 동적 SQL 기능을 구현하기 위해 사용한다.  

  • type 속성 : SQL Builder 클래스(Class 객체)를 속성값으로 설정한다.
  • method 속성 : SQL Builder 클래스의 SQL 명령을 생성하여 반환하는 메소드를 속성값으로 설정한다.

 


 

먼저 SQL Builder 클래스가 필요하기 때문에 하나 만들어주자

 

Provider 클래스(SQL Builder 클래스)는 SQL 명령을 생성하여 반환하는 메소드가 선언된 클래스이다.

 

SQL 객체 : SQL 명령 작성에 필요한 메소드를 이용하여 SQL 명령을 저장하기 위한 객체

참고: https://mybatis.org/mybatis-3/ko/statement-builders.html

 

  • SQL.toString() : SQL 객체에 저장된 SQL 명령을 문자열로 반환하는 메소드 

 

[MyHewonProvider.java] 

package xyz.itwill.mapper;

import org.apache.ibatis.jdbc.SQL;

//Provider 클래스(SQL Builder 클래스)
public class MyHewonProvider {
	//Java 명령으로 동적 SQL 기능을 이용하여 SQL 명령을 반환하는 메소드
	public String selectDynamicName(String name) {
		return new SQL() {{//SQL 명령을 저장하기 위한 객체 생성
			SELECT("hewon_id, hewon_name, hewon_phone");
			SELECT("hewon_email, hewon_status");
			FROM("myhewon");
			if(name != null && name.equals("")) {
				WHERE("hewon_name = #{name}");
			}
			ORDER_BY("hewon_id");
		}}.toString();//SQL 객체에 저장된 SQL 명령을 문자열로 반환
	}
}

 

인터페이스 매퍼 파일

@Results(value = {
	@Result(column = "hewon_id", property = "id")	
	, @Result(column = "hewon_name", property = "name")	
	, @Result(column = "hewon_phone", property = "phone")	
	, @Result(column = "hewon_email", property = "email")	
	, @Result(column = "hewon_status", property = "status")	
})
@SelectProvider(type = MyHewonProvider.class, method = "selectDynamicName")
List<MyHewon> selectDynamicHewonList(String name);

 

DAO 클래스

[MyHewonInterfaceDAO]

public class MyHewonInterfaceDAO extends AbstractSession {
	private static MyHewonInterfaceDAO _dao;

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

 

JSP 문서

[hewonListInterfaceSelect.jsp]

<%@page import="xyz.itwill.dao.MyHewonInterfaceDAO"%>
<%@page import="xyz.itwill.dto.MyHewon"%>
<%@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=MyHewonInterfaceDAO.getDAO().selectHewonList();//전체 검색
	} else {//전달값이 있는 경우
		hewonList=MyHewonInterfaceDAO.getDAO().selectNameHewonList(name);//조건 검색
	}
	*/
	
	List<MyHewon> hewonList=MyHewonInterfaceDAO.getDAO().selectDynamicHewonList(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>

 


 

provider 대신 @Select를 이용해서 동적SQL을 구현하는 것도 가능하다.

 

@Select 어노테이션의 value 속성값으로 script 엘리먼트를 사용하면 SQL 명령 작성시 Interface 동적 매퍼 파일에서 동적 SQL 관련 엘리먼트 사용이 가능하다. 

→ value 속성값으로 배열을 설정하여 SQL 명령을 순차적으로 작성하는 것이 가능하다.

 

@Results(value = {
	@Result(column = "hewon_id", property = "id")	
	, @Result(column = "hewon_name", property = "name")	
	, @Result(column = "hewon_phone", property = "phone")	
	, @Result(column = "hewon_email", property = "email")	
	, @Result(column = "hewon_status", property = "status")	
})

@Select({"<script>select hewon_id, hewon_name, hewon_phone, hewon_email, hewon_status from myhewon"
	,"<if test=\"name != null and name != ''\">where hewon_name = #{name}</if>" 
	,"order by hewon_id</script>"})
List<MyHewon> selectDynamicHewonList(String name);

 

 

 

 

 

 

 

 

 

 

 

 

 

'학원 > 복기' 카테고리의 다른 글

[Spring] 환경설정  (0) 2023.07.24
[Spring] Spring 프레임워크란?  (0) 2023.07.24
[MyBatis] 동적 SQL(Dynamic SQL)  (0) 2023.07.23
[Mybatis] cache 엘리먼트  (0) 2023.07.23
[Mybatis] 전달값 표현식 / bind 엘리먼트  (0) 2023.07.23