Mybatis
✒️ 2025-05-26 10:24 내용 수정
Java Object와 SQL 사이의 자동 Mapping을 지원하는 SQL Mapper 프레임워크
- Mybatis를 사용하지 않고 바로 JDBC를 사용하면 개발자가 반복적으로 작성할 코드가 많고, 서비스 로직과 쿼리 구분, 커넥션 풀 설정 등 관리가 어렵다.
- Mybatis를 사용하면 SQL을 별도의 파일로 분리해서 관리할 수 있으며, DB 연결에 필요한 코드도 JDBC를 바로 사용할 때보다 간단해진다.
- 다양한 프로그래밍 언어를 사용해서 구현할 수 있다.
주요 Component
| Component | 설명 |
|---|---|
| SqlMapConfig.xml | 데이터베이스 접속 주소 정보, Mapping 파일 경로 등 고정된 환경 정보 설정 |
| Mapping.xml | SQL문과 Mapping을 설정 |
| SqlSessionFactoryBuilder | Mybatis 설정 파일을 바탕으로 SqlSessionFactory 생성 |
| SqlSessionFactory | SqlSession을 생성 |
| SqlSession | 가장 핵심 클래스. SQL 실행이나 트랜잭션 관리 실행 |
| Thread-safe하지 않기에 thread마다 필요 시 생성됨 |
Mybatis 설정
- https://mvnrepository.com/artifact/org.mybatis/mybatis 에서 라이브러리를 다운 받는다.
- DB 연결에 필요한 라이브러리를 프로젝트에 추가한다.
- 라이브러리는
\src\main\webapp\WEB-INF\lib에 추가한다. - 오라클과 연동#사전 준비 참고.
- 라이브러리는
| 라이브러리 |
|---|
| commons-collections-3.2.1.jar |
| commons-dbcp-1.2.2.jar |
| commons-pool-1.4.jar |
| ojdbc8-23.3.0.23.09.jar |
| mybatis-3.5.15.jar |
프로젝트\src\main\webapp\META-INF폴더에 들어가는 context.xml을 추가한다.- 오라클과 연동#사전 준비 참고.
<?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>
- Java Resources에 config.mybatis 패키지를 만들고, 아래의 sqlMapConfig.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>
<environments default="">
<environment id="">
<transactionManager type="JDBC" />
<dataSource type="JNDI">
<property name="data_source"
value="java:comp/env/jdbc/oracle_test" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="config/mybatis/mapper/mapper파일이름.xml" />
</mappers>
</configuration>
- Java Resources에 config.mybatis 패키지에 config.mybatis.mapper 패키지를 만들고, mapper이름.xml 파일을 넣는다.
- 에러가 생긴다면 Downloading external resources is disabled 참고.
<?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="네임스페이스">
<select id="쿼리id" resultType="패키지이름.클래스이름">
<!-- SQL문 -->
</select>
</mapper>
- Ajax를 위한 파일도 webapp 폴더에 js 폴더를 만들어 HttpRequest.js 파일을 추가한다.
- 당장은 사용하지 않지만, 이후 실습을 위해 추가했다.
- Ajax(Asynchronous JavaScript and XML)#1. XMLHttpRequest 객체 참고.
var xhr = null;
function createRequest() {
if (xhr != null) {
return;
}
if (window.ActiveXObject) {
xhr = new ActiveXObject("Microsoft.XMLHTTP"); // IE 환경
} else {
xhr = new XMLHttpRequest(); // 기타 브라우저 환경
}
}
function sendRequest(url, param, callback, method) {
// HttpRequest 생성
createRequest();
// 전송 타입 구분
var httpMethod = (method != 'POST' && method != 'post') ? 'GET' : 'POST';
// 파라미터 구분
var httpParam = (param == null || param == '') ? null : param;
// 접근 url
var httpURL = url;
// 요청 방식이 GET이고 전달할 파라미터가 있다면 새 url 경로 제작
if (httpMethod == 'GET' && httpParam != null) {
httpURL = httpURL+'?'+httParam;
}
// 서버로 보낼 Ajax 요청 형식
xhr.open(httpMethod, httpURL, true);
// requestHeader 설정 : Content-Type 지정
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// 작업이 완료된 후 호출할 callback 메소드 지정
xhr.onreadystatechange = callback;
// Ajax 요청을 서버로 전달
xhr.send(httpMethod == 'POST' ? httpParam : null);
}
- 라이브러리들과 파일을 모두 넣으면 이런 모습이다.
DB와 연결
- DB와 연결할 MybatisConnector 클래스를 생성한다.
package service;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MybatisConnector {
static MybatisConnector single = null;
SqlSessionFactory factory = null;
public static MybatisConnector getInstance() {
if (single == null)
single = new MybatisConnector();
return single;
}
public MybatisConnector() {
// sqlMapConfig.xml 읽어오기
// sqlMapConfig.xml : mybatis에 대한 정보를 담고 있는 설정파일
try {
Reader reader = Resources.getResourceAsReader("config/mybatis/sqlMapConfig.xml");
// 위에서 읽어온 sqlMapConfig.xml에서 지정해둔 DB 접근 경로를 실제로 읽어옴
factory = new SqlSessionFactoryBuilder().build(reader);
reader.close();
} catch (Exception e) {
}
}
// sqlMapConfig.xml의 정보를 담고 있는 factory객체를 반환
public SqlSessionFactory getSqlSessionFactory() {
return factory;
}
}
- 조회한 데이터를 저장하기 위한 DTO 클래스를 만들어준다.
package dto;
import lombok.Data;
@Data
public class DeptDTO {
private int deptno;
private String dname, loc;
}
- 데이터베이스에 접근하기 위한 DAO 클래스를 만들어준다.
- 데이터 객체#DAO(Data Access Object) 참고.
- DAO에서 MybatisConnector 클래스를 생성하여 DB에 연결한다.
- select() 메소드에서
sqlSession.selectList("네임스페이스.쿼리식별id")의 네임스페이스와 쿼리식별id는 mapper이름.xml 파일에서 사용된다.
package dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import dto.DeptDTO;
import service.MybatisConnector;
public class DeptDAO {
// SqlSessionFactory 객체 생성
SqlSessionFactory factory;
static DeptDAO single = null;
public static DeptDAO getInstance() {
if (single == null)
single = new DeptDAO();
return single;
}
// MybatisConnector 객체 가져오기
public DeptDAO() {
factory = MybatisConnector.getInstance().getSqlSessionFactory();
}
// 부서 테이블 조회
public List<DeptDTO> select() {
SqlSession sqlSession = factory.openSession();
List<DeptDTO> list = sqlSession.selectList("dept.dept_list"); // 네임스페이스.쿼리식별id
sqlSession.close();
return list;
}
}
- mapper이름.xml 파일을 DAO 클래스의 select() 메소드에 작성했던 네임 스페이스, 쿼리 식별 id, 그리고 반환 타입에 맞춰 수정하고, 조회를 위해 SQL문을 작성한다.
<?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">
<select id="dept_list" resultType="dto.DeptDTO">
SELECT * FROM DEPT
</select>
</mapper>
- sqlMapConfig.xml 파일에 mapper이름.xml을 <mappers> 태그 내에 추가한다.
<mapper resource="config/mybatis/mapper/mapper이름.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>
<environments default="">
<environment id="">
<transactionManager type="JDBC" />
<dataSource type="JNDI">
<property name="data_source"
value="java:comp/env/jdbc/oracle_test" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="config/mybatis/mapper/dept.xml" />
<mapper resource="config/mybatis/mapper/sawon.xml" />
<mapper resource="config/mybatis/mapper/gogek.xml" />
</mappers>
</configuration>
- 데이터베이스 조회를 실행하고 결과를 가져올 Servlet을 생성한다.
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 dto.DeptDTO;
@WebServlet("/dept_list")
public class DeptListAction extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 조회 결과를 저장한 list
List<DeptDTO> list = DeptDAO.getInstance().select();
// 바인딩
request.setAttribute("list", list);
// 포워딩
RequestDispatcher disp = request.getRequestDispatcher("dept_list.jsp");
disp.forward(request, response);
}
}
- 데이터베이스 조회 결과를 확인할 JSP를 작성한다.
<%@ 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="dto" items="${list}">
<tr>
<td>${dto.deptno}</td>
<td>${dto.dname}</td>
<td>${dto.loc}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
- Servlet을 실행하여 결과를 확인한다.