장점 : 개발 시간 단축 / 성능 향상 / 유지 보수성 향상
단점 : 프레임워크 학습 필요, 선택의 어려움, 유연성 부족
개발자가 지정한 SQL, 저장프로시저 그리고 몇가지 고급 매핑을 지원하는 퍼시스턴스 프레임워크
JDBC로 처리하는 상당부분의 코드와 파라미터 설정및 결과 매핑을 대신해준다
xml파일에 데이터베이스 처리에 관한 sql문 설정 후 자바 소스에서 간단하게 연결하여 데이터를 처리할 수 있음
매핑하기 위해 XML과 애노테이션을 사용 (XML -> 애노테이션으로 가는 추세)
Mybatis 설정
lib
- jdbc 드라이버
- mybatis 프레임워크
- log출력용 라이브러리 (3가지 필요)
설정파일
- 데이터베이스 접속용
- sql mapper 파일
log4j.xml(작업진행에 대한 로그 출력하는 프레임 워크)
데이터베이스와 접속되는 내용을 설정해줌
dynamic web project --> maven(gradle) project로 대치
log4.xml - 작업진행에 대한 로그 출력하는 프레임 워크
myBatisConfig.xml - 데이터베이스와 접속되는 내용을 설정해줌
(2개도 설정 가능, enviroments의 default에 적힌 것에 따라 사용 결정)
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisEx01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//넣은 설정파일 xml 이름 변수에 넣기
String resource = "myBatisConfig.xml";
InputStream is = null;
try {
is = Resources.getResourceAsStream( resource );
// sqlSessionFactory 연결
SqlSessionFactory sqlSessionFactory
= new SqlSessionFactoryBuilder().build( is );
System.out.println("설정 호출");
} catch (IOException e) {
System.out.println("[에러]" + e.getMessage());
} finally {
if(is != null) try { is.close(); } catch(IOException e) {}
}
}
}
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisEx01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//넣은 설정파일 xml 이름 변수에 넣기
String resource = "myBatisConfig.xml";
InputStream is = null;
SqlSession sqlSession = null;
try {
is = Resources.getResourceAsStream( resource );
SqlSessionFactory sqlSessionFactory
= new SqlSessionFactoryBuilder().build( is );
System.out.println("설정 호출");
//session 얻기
sqlSession = sqlSessionFactory.openSession();
System.out.println("연결 성공");
} catch (IOException e) {
System.out.println("[에러]" + e.getMessage());
} finally {
if(sqlSession != null) sqlSession.close();
if(is != null) try { is.close(); } catch(IOException e) {}
}
}
}
//데이터 가져오기
//한 줄의 데이터 가져오기 = selectOne (데이터가 여러 개면 에러남)
DeptTO to = (DeptTO) sqlSession.selectOne("deptlist");
System.out.println(to.getDeptno());
System.out.println(to.getDname());
System.out.println(to.getLoc());
//여러 줄의 데이터 가져오기 = selectList
연결성공 밑에 쓰기
//여러 줄의 데이터 가져오기 = selectList
List<DeptTO> lists = sqlSession.selectList("selectall"); //select의 id부분 넣기
for(DeptTO to : lists) {
System.out.println(to.getDeptno());
System.out.println(to.getDname());
System.out.println(to.getLoc());
}
list(arraylist) 형식으로 가져오기 (ArrayList로 가져올 때는 형변환 해줘야함)
log4j.xml
<root>
<level value="DEBUG" />
<appender-ref ref="console" />
</root>
myBatisConfig.xml
<configuration>
<environments default="mariadb1">
<environment id="mariadb1">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="org.mariadb.jdbc.Driver"/>
<property name="url" value="jdbc:mariadb://localhost:3306/sample"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
</configuration>
mapper.xml
<mapper namespace="mybatis1">
<select id="selectone" resultType="model1.DeptTO">
select deptno, dname, loc
from dept
where deptno = 10;
</select>
</mapper>
후에 model1 패키지 - DeptTO 클래스 만들고 myBatisConfig.xml 가서 mapper 위치 잡아주기
environments 밑에
<mappers>
<mapper resource="model1/mapper.xml" />
</mappers>
<%@ page import="java.io.IOException" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="org.apache.ibatis.io.Resources" %>
<%@ page import="org.apache.ibatis.session.SqlSession" %>
<%@ page import="org.apache.ibatis.session.SqlSessionFactory" %>
<%@ page import="org.apache.ibatis.session.SqlSessionFactoryBuilder" %>
<%@ page import="model1.DeptTO" %>
한 줄 받기
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.io.IOException" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="org.apache.ibatis.io.Resources" %>
<%@ page import="org.apache.ibatis.session.SqlSession" %>
<%@ page import="org.apache.ibatis.session.SqlSessionFactory" %>
<%@ page import="org.apache.ibatis.session.SqlSessionFactoryBuilder" %>
<%@ page import="model1.DeptTO" %>
<%
String resource = "myBatisConfig.xml";
InputStream is = null;
SqlSession sqlSession = null;
StringBuilder sbHtml = new StringBuilder();
try {
is = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory
= new SqlSessionFactoryBuilder().build(is);
sqlSession = sqlSessionFactory.openSession();
DeptTO to = (DeptTO) sqlSession.selectOne("selectone");
sbHtml.append("<table border='1' width='800'>");
sbHtml.append("<tr>");
sbHtml.append("<td>" + to.getDeptno() + "</td>");
sbHtml.append("<td>" + to.getDname() + "</td>");
sbHtml.append("<td>" + to.getLoc() + "</td>");
sbHtml.append("</tr>");
sbHtml.append("</table>");
} catch(IOException e) {
System.out.println("[에러] : " + e.getMessage());
} finally {
if(sqlSession != null) sqlSession.close();
if(is != null) try { is.close(); } catch(IOException e) {}
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%=sbHtml %>
</body>
</html>
실행 로그
<select id="selectparamone1" parameterType="String" resultType="model1.DeptTO">
select deptno, dname, loc
from dept
where deptno = #{deptno}; <-- #{deptno}를 줘서 ? 와 같은 효과 주기
</select>
후에 jsp 파일에서
DeptTO to = (DeptTO) sqlSession.selectOne("selectparamone1", "20");
<-- 매개변수 하나 더 추가(deptno 20을 가져오겠다!)
parameterType을 model.DeptTO로 받아준다.
<select id="selectparamone3" parameterType="model.DeptTO" resultType="model1.DeptTO">
select deptno, dname, loc
from dept
where deptno = #{deptno} and dname=#{dname}
</select>
jsp 파일에서 DeptTO 타입 변수 하나 만들고 set으로 값 집어넣기 - > sqlSession에 변수 넣기
DeptTO paramTO = new DeptTO();
paramTO.setDeptno("30");
paramTO.setDname("SALES");
DeptTO to = (DeptTO) sqlSession.selectOne("selectparamone3", paramTO);
변경점 : emp정보이므로, 데이터베이스 dept -> emp에 맞게 설정 바꾸기
like를 쓸 경우 정보가 하나 이상이 나올 확률이 높으니까 selectList를 사용
mapper.xmp 설정
<select id="selectone2" parameterType="String" resultType="model1.EmpTO">
select empno, ename, job, hiredate, sal, comm, deptno
from emp
where ename like #{ename}
</select>
jsp 작업
<%
String resource = "myBatisConfig.xml";
InputStream is = null;
SqlSession sqlSession = null;
StringBuilder sbHtml = new StringBuilder();
try {
is = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory
= new SqlSessionFactoryBuilder().build(is);
sqlSession = sqlSessionFactory.openSession();
ArrayList<EmpTO> lists = (ArrayList) sqlSession.selectList("selectone2", "S%");
sbHtml.append("<table border='1' width='800'>");
sbHtml.append("<tr>");
sbHtml.append("<td>" + to.getEmpno() + "</td>");
sbHtml.append("<td>" + to.getEname() + "</td>");
sbHtml.append("<td>" + to.getJob() + "</td>");
sbHtml.append("<td>" + to.getHiredate() + "</td>");
sbHtml.append("<td>" + to.getSal() + "</td>");
sbHtml.append("<td>" + to.getComm() + "</td>");
sbHtml.append("<td>" + to.getDeptno() + "</td>");
sbHtml.append("</tr>");
sbHtml.append("</table>");
} catch(IOException e) {
System.out.println("[에러] : " + e.getMessage());
} finally {
if(sqlSession != null) sqlSession.close();
if(is != null) try { is.close(); } catch(IOException e) {}
}
%>
mapper.xml에서 아예 %를 붙여도 된다.
<select id="selectone3" parameterType="String" resultType="model1.EmpTO">
select empno, ename, job, hiredate, sal, comm, deptno
from emp
where ename like concat(#{ ename }, '%'); <--concat(문자열 결합)을 이용하여 처음부터 %를 붙여버림
</select>
여기서는 s%에서 %빼주면 된다( 실행결과는 위와 동일 )
ArrayList<EmpTO> lists = (ArrayList) sqlSession.selectList("selectone2", "S");
mapper.xml
<insert id="insert1" parameterType="model1.DeptTO">
insert into dept2 (deptno, dname, loc)
values (#{deptno}, #{dname}, #{loc})
</insert>
<%
String resource = "myBatisConfig.xml";
InputStream is = null;
SqlSession sqlSession = null;
StringBuilder sbHtml = new StringBuilder();
try {
is = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory
= new SqlSessionFactoryBuilder().build(is);
sqlSession = sqlSessionFactory.openSession();
DeptTO to = new DeptTO();
to.setDeptno("80");
to.setDname("총무부");
to.setLoc("도쿄");
int result = sqlSession.insert("insert1", to);
if(result == 1) {
sqlSession.commit();
sbHtml.append("입력 성공 : " + result);
}
} catch(IOException e) {
System.out.println("[에러] : " + e.getMessage());
} finally {
if(sqlSession != null) sqlSession.close();
if(is != null) try { is.close(); } catch(IOException e) {}
}
%>
실행하면 정상 실행되어도 db에 들어가져있지 않음 <- insert, update, delete를 사용할 경우 정상 검사되기 전까지는 메모리에서 보관하고 있음(transaction)
commit - 인정 / rollback - 되돌림
을 통하여 보관된 메모리 사용 가능
if(result == 1) {
sqlSession.commit(); //보관된 것 적용시킨다! 라는 뜻
sbHtml.append("입력 성공 : " + result);
}
매번 하기 번거로워서 openSession()에다 true를 줘서 무조건 commit 시키게 만든다(auto commit)
sqlSession = sqlSessionFactory.openSession(true); <-- true 넣기
DeptTO to = new DeptTO();
to.setDeptno("90");
to.setDname("인사부");
to.setLoc("서울");
int result = sqlSession.insert("insert1", to);
sbHtml.append("입력 성공 : " + result);
insert와 형식은 같다.
mapper.xml
<update id="update1" parameterType="model1.DeptTO">
update dept2
set dname=#{dname}
where deptno=#{deptno}
</update>
<delete id="delete1" parameterType="model1.DeptTO">
delete from dept2
where deptno=#{deptno}
</delete>
기존 db
update
DeptTO to = new DeptTO();
to.setDeptno("80");
to.setDname("회계부");
int result = sqlSession.update("update1", to);
delete
DeptTO to = new DeptTO();
to.setDeptno("80");
int result = sqlSession.delete("delete1", to);
to dao -> select
package model1;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class DeptDAO {
private SqlSession sqlSession;
public DeptDAO() {
String resource = "myBatisConfig.xml";
InputStream is = null;
try {
is = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory
= new SqlSessionFactoryBuilder().build(is);
sqlSession = sqlSessionFactory.openSession(true);
} catch (IOException e) {
System.out.println("[에러] : " + e.getMessage());
} finally {
if(is != null) try { is.close(); } catch(IOException e) {}
}
}
public List<DeptTO> selectList() {
List<DeptTO> lists = sqlSession.selectList("selectlist");
if(sqlSession != null) sqlSession.close();
return lists;
}
zipcodeDAO
package model1;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class ZipcodeDAO {
private SqlSession sqlSession;
public ZipcodeDAO() {
String resource = "myBatisConfig.xml";
InputStream is = null;
try {
is = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory
= new SqlSessionFactoryBuilder().build(is);
sqlSession = sqlSessionFactory.openSession(true);
} catch (IOException e) {
System.out.println("[에러] : " + e.getMessage());
} finally {
if(is != null) try { is.close(); } catch(IOException e) {}
}
}
public ArrayList<ZipcodeTO> zipcodeSearch(String strDong) {
ArrayList<ZipcodeTO> lists = (ArrayList) sqlSession.selectList("zipcodelist", strDong + "%");
if(sqlSession != null) sqlSession.close();
return lists;
}
}
zipcodeSearch.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="model1.ZipcodeTO" %>
<%@ page import="model1.ZipcodeDAO" %>
<%@ page import="java.util.ArrayList" %>
<%
request.setCharacterEncoding("utf-8");
String strDong = "";
if(request.getParameter("dong") != null) {
strDong = request.getParameter("dong");
}
ZipcodeDAO dao = new ZipcodeDAO();
ArrayList<ZipcodeTO> lists = dao.zipcodeSearch(strDong);
StringBuilder sbHtml = new StringBuilder();
sbHtml.append("<table>");
for(ZipcodeTO to : lists) {
sbHtml.append("<tr>");
sbHtml.append("<td>" + to.getZipcode() + "</td>");
sbHtml.append("<td>" + to.getSido() + "</td>");
sbHtml.append("<td>" + to.getGugun() + "</td>");
sbHtml.append("<td>" + to.getDong() + "</td>");
sbHtml.append("<td>" + to.getRi() + "</td>");
sbHtml.append("<td>" + to.getBunji() + "</td>");
sbHtml.append("</tr>");
}
sbHtml.append("</table>");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="zipcodeSearch.jsp" method="post">
동 이름 : <input type="text" name="dong" />
<input type="submit" value="검색" />
</form>
<br><hr><br>
<%=sbHtml %>
</body>
</html>
기존의 dao에 sql구문을 myBatis mapper.xml에서 써줘, 완전히 변환하여 dao에 sql구문이 없어야 함
-> 기존 쓰던 작업시간보다 훨씬 더 줄어든다.
board.xml
<mapper namespace="mybatis1">
<select id="list" resultType="model1.BoardTO">
select seq, subject, writer, date_format(wdate,'%Y-%m-%d') wdate, hit
from board
order by seq desc;
</select>
//view처럼 seq 정보를 받는 애들은 select시에 seq을 같이 가져온다.
<select id="view" parameterType="model1.BoardTO" resultType="model1.BoardTO">
select seq, subject, writer, mail, wip, date_format(wdate,'%Y-%m-%d')wdate, hit, content
from board
where seq=#{seq}
</select>
<update id="view_hit" parameterType="model1.BoardTO">
update board set hit=hit+1
where seq=#{seq}
</update>
<insert id="write_ok" parameterType="model1.BoardTO">
insert into
board values(0,#{subject}, #{writer}, #{mail}, #{password}, #{content}, 0, #{wip}, now());
</insert>
<select id="modify" parameterType="model1.BoardTO" resultType="model1.BoardTO">
select seq, subject, writer, mail, content
from board
where seq = #{seq};
</select>
<update id="modify_ok" parameterType="model1.BoardTO">
update board set subject = #{subject}, mail = #{mail}, content = #{content}
where seq = #{seq} and password = #{password};
</update>
<select id="delete" parameterType="model1.BoardTO" resultType="model1.BoardTO">
select seq, subject, writer, mail, content
from board
where seq = #{seq};
</select>
<delete id="delete_ok" parameterType="model1.BoardTO">
delete from board
where seq = #{seq} and password = #{password};
</delete>
</mapper>
BoardDAO
package model1;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.naming.NamingException;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class BoardDAO {
private SqlSession sqlSession;
// 생성자가 필요
public BoardDAO() {
String resource = "myBatisConfig.xml";
InputStream is = null;
try {
is = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory
= new SqlSessionFactoryBuilder().build(is);
sqlSession = sqlSessionFactory.openSession(true);
} catch (IOException e) {
System.out.println("[에러] : " + e.getMessage());
} finally {
if(is != null) try { is.close(); } catch(IOException e) {}
}
}
public void boardWrite() {
}
// BoardTO to는 write에서 받은 데이터를 집어넣는다
public int boardWriteOk(BoardTO to) {
int flag = 1;
int result = sqlSession.insert("write_ok", to);
if(result == 1) {
flag = 0;
}
if(sqlSession != null) sqlSession.close();
return flag;
}
// list는 ArrayList로 받아온다
public ArrayList<BoardTO> boardList() {
ArrayList<BoardTO> datas = (ArrayList)sqlSession.selectList("list");
if(sqlSession != null) sqlSession.close();
return datas;
}
// to에 seq가 들어가서 update하고 select 함
public BoardTO boardView(BoardTO to) {
sqlSession.update("view_hit", to);
to = sqlSession.selectOne("view", to);
if(sqlSession != null) sqlSession.close();
return to;
}
public BoardTO boardModify(BoardTO to) {
to = sqlSession.selectOne("modify", to);
if(sqlSession != null) sqlSession.close();
return to;
}
public int boardModifyOk(BoardTO to) {
int flag = 2;
int result = sqlSession.update("modify_ok",to);
if(result == 0) {
flag = 1;
}
else if(result == 1) {
flag = 0;
}
if(sqlSession != null) sqlSession.close();
return flag;
}
public BoardTO boardDelete(BoardTO to) {
to = sqlSession.selectOne("delete", to);
if(sqlSession != null) sqlSession.close();
return to;
}
public int boardDeleteOk(BoardTO to) {
int flag = 2;
int result = sqlSession.delete("delete_ok",to);
if(result == 0) {
flag = 1;
}
else if(result == 1) {
flag = 0;
}
if(sqlSession != null) sqlSession.close();
return flag;
}
}
JSP쪽은 수정 X
결과도 똑같다.