3 분 소요

MyBatis


MyBatis

MyBatis는 Java 소스 코드 안에 SQL 문을 작성하면 코드가 길어지고 SQL 구문이 섞여 있어 유지 보수가 힘들다는 단점을 극복하기 위해 고안되었다. 기존 JDBC 방식과 달리 SQL 문을 XML 파일에 따로 작성하고 관리하기 때문에 수정의 편리함이 존재한다. 또 XML 형태로 쓰인 JDBC 코드라고 생각해도 될 만큼 JDBC의 모든 기능을 제공한다.


MyBatis의 특징

복잡한 쿼리에 강하고 프로그램 코드와 SQL 쿼리의 분리로 코드가 간결해져 가독성이 높고 유지보수성이 향상된다.


MyBatis다운로드

https://blog.mybatis.org/p/products.html

jsp21_1

jsp21_2

위와 같이 라이브러리를 직접 jar파일로 불러와 사용할 수 있고 아래 코드처럼 Maven 개발 환경이라면
https://mvnrepository.com/ 에서 라이브러리 코드를 가져와도된다.

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.9</version>
</dependency>

Maven 환경에서 MyBatis를 통해 DB와 연동하여 로그인 로직을 구현해보자.

SqlMapConfig.java

package com.koreait.db;

import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class SqlMapConfig {
	private static SqlSessionFactory sqlsession;
	
	static {
		try {
			String resource = "com/koreait/db/config.xml";
			Reader reader = Resources.getResourceAsReader(resource);
			sqlsession = new SqlSessionFactoryBuilder().build(reader);
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static SqlSessionFactory getSqlMapInstance() {
		return sqlsession;
	}
}


Dbconn.java

package com.koreait.db;

import java.sql.Connection;
import java.sql.DriverManager;

public class Dbconn {
	public static Connection getConnection() {
		Connection conn = null;
		
		try {
			String url = "jdbc:mysql://localhost:3306/aiclass";
			String uid = "YYYY";
			String upw = "XXXX";
			Class.forName("com.mysql.cj.jdbc.Driver");
			conn = DriverManager.getConnection(url, uid, upw);
		}catch(Exception e) {
			e.printStackTrace();
		}
		return conn;
	}
}


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>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/aiclass"/>
        <property name="username" value="root"/>
        <property name="password" value="1234"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="com/koreait/db/member.xml"/>
  </mappers>
</configuration>


member.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="Member">
  <select id="login" parameterType="map" resultType="map">
    select mem_idx, mem_userid, mem_name from tb_member where mem_userid=#{mem_userid} and mem_userpw=#{mem_userpw};
  </select>
</mapper>


MemberDAO.java

package com.koreait.member;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Scanner;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.koreait.db.Dbconn;
import com.koreait.db.SqlMapConfig;

public class MemberDAO {

	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs;
	String sql = "";
	
	SqlSessionFactory ssf = SqlMapConfig.getSqlMapInstance();
	SqlSession sqlsession;
	
	public MemberDAO() {
		sqlsession = ssf.openSession(true); // 설정시 자동 commit
		System.out.println("마이바티스 설정 성공!");
	}

	public MemberDTO login(MemberDTO member) {
		HashMap<String, String> dataMap = new HashMap();
		dataMap.put("mem_userid", member.getUserid());
		dataMap.put("mem_userpw", member.getUserpw());
		dataMap = sqlsession.selectOne("Member.login", dataMap);
		
		if(dataMap != null) {
			member.setIdx(Integer.parseInt(String.valueOf(dataMap.get("mem_idx"))));
			member.setUserid(dataMap.get("mem_userid"));
			member.setUsername(dataMap.get("mem_name"));
			return member;
		}
		return null;
	}

}


MemberDTO.java

package com.koreait.member;

import java.util.Arrays;

public class MemberDTO {
	private int idx;
	private String userid;
	private String userpw;

	public int getIdx() {
		return idx;
	}

	public void setIdx(int idx) {
		this.idx = idx;
	}

	public String getUserid() {
		return userid;
	}

	public void setUserid(String userid) {
		this.userid = userid;
	}

	public String getUserpw() {
		return userpw;
	}

	public void setUserpw(String userpw) {
		this.userpw = userpw;
	}

}


login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	String userid = null;
	String name = null;
	if(session.getAttribute("userid") != null){
		userid = (String)session.getAttribute("userid");
 		name = (String)session.getAttribute("name");
	}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인</title>
</head>
<body>
	<h2>로그인</h2>
<%
	if(userid == null){
%>
	<form method="post" action="login_ok.jsp">
		<p>아이디 : <input type="text" name="userid"></p>
		<p>비밀번호 : <input type="password" name="userpw"></p>
		<p><input type="submit" value="로그인"></p>
		<p>회원이 아니신가요? <a href='./regist.jsp'>회원가입</a></p>
	</form>
<%
	}else{
%>
	<h3><%=userid%>(<%=name%>)님 환영합니다.</h3>
	<p>
		<input type="button" value="커뮤니티" onclick="location.href='./board/list.jsp'">
		<input type="button" value="정보수정" onclick="location.href='info.jsp'">
		<input type="button" value="로그아웃" onclick="location.href='logout.jsp'">
	</p>
<%
	}
%>
</body>
</html>


login_ok.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.*"%>

<jsp:useBean id="member" class="com.koreait.member.MemberDTO"/>
<jsp:setProperty property="*" name="member"/>
<jsp:useBean id="dao" class="com.koreait.member.MemberDAO"/>
<%
	if((member = dao.login(member)) != null){
		session.setAttribute("userid", member.getUserid());
		session.setAttribute("name", member.getUsername());
		session.setAttribute("idx", member.getIdx());
%>
	<script>
		alert('로그인 되었습니다');
		location.href="login.jsp";
	</script>
<%			
	}else{	// 로그인 실패
%>
	<script>
		alert('아이디 또는 비밀번호를 확인하세요');
		history.back();
	</script>
<%
	}	
%>


MemberDAO에서 login() 함수를 호출하게되는데, login() 함수를 자세히 살펴보면

public MemberDTO login(MemberDTO member) {
    HashMap<String, String> dataMap = new HashMap();
    dataMap.put("mem_userid", member.getUserid());
    dataMap.put("mem_userpw", member.getUserpw());
    dataMap = sqlsession.selectOne("Member.login", dataMap);

    if(dataMap != null) {
        member.setIdx(Integer.parseInt(String.valueOf(dataMap.get("mem_idx"))));
        member.setUserid(dataMap.get("mem_userid"));
        member.setUsername(dataMap.get("mem_name"));
        return member;
    }
    return null;
}

DTO로 받은 member 데이터에서 userid와 userpw를 map형태로 dataMap에 저장하고 이를 member.xml의 login의 쿼리에 대입하여 쿼리결과를 dataMap에 반환해준다.

member.xml을 보면 마이바티스의 장점인 모든 쿼리를 xml 파일에서 확실히 용이하게 관리가 가능하다는 의미를 알 것 같다.