1) MyBatis란?
마이 바티스(MyBatis)란 자바의 프레임워크 중 하나로 XML이나 애너테이션(annotation)을 사용하여 저장 프로시저나 SQL문으로 객체들을 연결시킬 수 있는 소프트웨어이다. 마이 바티스에서는 프로그램에 있는 SQL 쿼리들을 한 구성 파일에 구성하여 프로그램 코드와 SQL을 분리할 수 있는 장점을 지닌다. 마이 바티스를 활용하면 복잡한 JDBC 코드를 깔끔하게 정리할 수 있다는 장점이 있다. XML 형태로 작성된 JDBC 코드라고 말할 정도로 JDBC의 모든 기능을 제공한다.
2) MyBatis 활용
간단하게 위의 이미지처럼 오라클에 저장된 부서테이블의 부서 번호, 부서 이름, 부서위치를 출력해보려 한다.
--부서테이블
CREATE TABLE DEPT(
DEPTNO NUMBER(3) PRIMARY KEY, --부서번호
DNAME VARCHAR2(10), --부서명
LOCATION VARCHAR2(5) --부서위치
);
INSERT INTO DEPT VALUES(10, '총무부', '101');
INSERT INTO DEPT VALUES(20, '영업부', '202');
INSERT INTO DEPT VALUES(30, '전산실', '303');
INSERT INTO DEPT VALUES(40, '관리부', '404');
INSERT INTO DEPT VALUES(50, '경리부', '505');
테이블 구조와 필요한 데이터들을 기존에 오라클에 넣어주었다. 위의 코드에는 나와있지 않지만, 데이터를 입력하는 Insert 구문을 작성한 뒤에는 반드시 Commit을 해주자.
package vo;
public class DeptVO {
private int deptno;
private String dname, location;
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
위의 코드는 오라클에 입력한 부서 번호, 부서 이름, 부서위치를 활용하기 위한 클래스이다.
package dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import service.MyBatisConnector;
import vo.DeptVO;
public class DeptDAO {
SqlSessionFactory factory;
// single-ton pattern:
// 객체1개만생성해서 지속적으로 서비스하자
static DeptDAO single = null;
public static DeptDAO getInstance() {
//생성되지 않았으면 생성
if (single == null)
single = new DeptDAO();
//생성된 객체정보를 반환
return single;
}
public DeptDAO() {
//커넥터에서 디비의 접근할 수 있는 내용을 알고 있는 팩토리를 받아옴
factory = MyBatisConnector.getInstance().getFactory();
}
//부서테이블 조회
public List<DeptVO> select() {
//SqlSession : DB에 쿼리문을 실제로 요청하는 객체
SqlSession sqlSession = factory.openSession();
//DB접근을 통해 얻어온 결과를 list에 저장
List<DeptVO> list =sqlSession.selectList("dept.dept_list");
//DB접근을 위해 사용한 sqlSession은 마지막에 꼭 닫아줘야함
sqlSession.close();
return list;
}
}
다음은 데이터베이스에 실질적으로 연동하는 코드를 작성한 DeptDAO.java 파일이다. 싱글톤 형태로 작성하여 객체를 하나만 사용하여 다른 코드에서도 자유롭게 사용할 수 있도록 작성하였다. 이후 생성자를 통해 커넥터에서 디비에 접근할 수 있는 내용을 알고 있는 팩토리를 받아온 뒤 아래에 select()라는 조회 메서드를 만들어주었다. 메서드 안에는 SqlSession을 사용하여 디비에 쿼리문을 요청하고, 전에 만들어둔 vo클래스를 통해 결과들을 리스트 형식으로 저장한다.
만약, 조회가 아니라 INSERT, UPDATE, DELETE 등 다양한 디비 작업들을 하려면 아래에 메서드 형식으로 추가해주면 된다.
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource
auth="Container"
name="jdbc/oracle_test"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.driver.OracleDriver"
factory="org.apache.commons.dbcp.BasicDataSourceFactory"
url="jdbc:oracle:thin:@localhost:1521:xe"
username="유저명입력" password="비밀번호입력"
maxActive="20" maxIdle="10" maxWait="1"/>
</Context>
자바와 데이터베이스를 연결하는 방식은 여러 가지겠지만, 이번엔 context.xml을 만들어주어, 미리 세팅을 해주었다.
username과 password 부분에 본인의 오라클 유저명과 비밀번호를 입력해주면 된다.
<?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>
<environments default="">
<environment id="">
<transactionManager type="JDBC" />
<!-- mybatis 사용을 위해서 JNDI를 찾아주는 코드 -->
<!-- context.xml으로 접근하고 context.xml에 작성된 계정으로 로그인해주는 방식 -->
<dataSource type="JNDI">
<!-- jdbc~~부분은 context.xml의 이름을 작성해주면 됨. -->
<property name="data_source"
value="java:comp/env/jdbc/oracle_test" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="config/mybatis/mapper/dept.xml" />
</mappers>
</configuration>
다음으로 위의 코드는 마이 바티스를 사용하기 위한 기본 셋팅이라고 보면 될 것같다. 마이바티스를 사용하기 위해서 JNDI를 찾아주는 코드로, context.xml에 작성된 계정으로 로그인해주는 방식이다. 이후 mapper부분에 sql문을 작성해둔 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="dept">
<!-- mapper : DB에 쿼리문을 요청하고 결과를 돌려받는 속성파일 -->
<select id="dept_list" resultType="vo.DeptVO">
select * from dept
</select>
</mapper>
위에서 언급했던 sql문을 작성해둔 xml파일이다. mapper의 namespace를 dept로 해주었고, 우린 부서 목록을 조회를 할 것이기 때문에 select를 사용하고, id는 dept_list로 지정했다. 또한 resultType을 vo클래스로 하였다.
아까 위의 DeptDAO.java 파일에서 sqlSession.select() 코드를 작성할 때 위 코드의 mapper의 namespace와 select의 id를.으로 연결하여 작성한 것이다.
여기서 가장 주의해야 할 점은 오라클에서처럼 ;(세미콜론)을 작성하면 안 된다는 것이다. 이 점만 명심하자.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<table border="1">
<caption>:::부서목록:::</caption>
<tr>
<th>부서번호</th>
<th>부서이름</th>
<th>부서위치</th>
</tr>
<c:forEach var="vo" items="${list }">
<tr>
<td>${vo.deptno }</td>
<td>${vo.dname }</td>
<td>${vo.location }</td>
</tr>
</c:forEach>
</table>
</body>
</html>
위 코드는 우리가 최종적으로 보여주고 싶은 화면의 틀을 작성한 코드이다. table을 활용하여 캡션과 head부분을 작성해주었고, 안에 들어갈 데이터는 forEach를 활용하여 list의 길이만큼 반복하여 출력하도록 하였다.
package action;
import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.DeptDAO;
import vo.DeptVO;
/**
* Servlet implementation class DeptListAction
*/
@WebServlet("/dept_list.do")
public class DeptListAction extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 부서목록 가져오기
List<DeptVO> list = DeptDAO.getInstance().select();
//list 바인딩
request.setAttribute("list", list);
//포워딩
RequestDispatcher disp = request.getRequestDispatcher("dept_list.jsp");
disp.forward(request, response);
}
}
마지막으로 서블릿 파일이다. 매핑명은 dept_list.do로 설정해주었고, 위에 작성한 DAO를 활용하여 부서 목록 리스트를 가져온다. 이후 이 리스트를 바인딩하여 jsp파일로 포워딩해주는 코드이다. 데이터베이스에서 올바르게 데이터를 받아와 화면에 출력하기 위해서는 dept_list.jsp를 실행시키는 것이 아니라, 서블릿 파일을 실행시켜야 데이터들이 함께 출력되니 이 점도 주의하자!
마치며
오늘은 마이 바티스를 활용하여 간단한 부서 목록을 출력하는 예제를 해보았다. 출력은 간단하지만, 필요한 코드가 한 두 개가 아니고, 여러 파일에서 데이터들이 이동하는 것이 가장 이해하기 어려웠다.
나머지 전반적인 흐름은 어느 정도 이해가 되지만, 사실 가장 이해가 안 되는 부분은 xml코드이다. xml코드를 좀 더 분석하며 다른 예제들을 추가적으로 해볼 계획이다.