JSP

[JSP] Mybatis_1

(งᐛ)ว 2023. 11. 6. 23:37
728x90

Mybatis
자바 오브젝트와 sql 사이의 자동 매핑 기능을 지원하는 프레임워크 
sql을 별도의 파일로 분리해서 관리할 수 있다. 

Mybatis를 사용하지 않고 JDBC를 사용하는 경우의 문제점 :
개발자가 반복적으로 작성해야할 코드가 많고 서비스 로직 코드와 쿼리를 분리하기 어렵다. 
커넥션 풀의 설정 등 개발자가 신경써야할 부분이 많아 여러 어려움이 있다.

Mybatis의 특징 
1. 쉬운 접근성

2. 코드의 간결함

3. JDBC의 대부분을 제공
4. 복잡한 JDBC코드를 덜어내고 깔끔한 소스코드 유지가능  

 

Mybatis 프레임워크 라이브러리 다운로드
https://mvnrepository.com

 


필요한 파일을 먼저 세팅하자

 

 

1️⃣부서테이블 만들기

 

MyBatisConnector.java

package service;

import java.io.IOException;

//1. SqlSessionFactoryBuilder가 Mybatis 설정파일을 참고하여 SqlSessionFactory 객체를 생성한다.
//2. 웹에서 데이터 접근 작업시 SqlSessionFactory는 매 요청마다 SqlSession객체를 생성한다.
//3. SqlSession 객체를 통해 DB작업을 진행하는데 작업시 수행하는 쿼리는 mapper패키지에 담겨있다. 

public class MyBatisConnector {
    	
	SqlSessionFactory  factory=null;
	private static MyBatisConnector connector; 
	
	
	//sqlMapConfig.xml 읽어오기 
	public MyBatisConnector()
	{
		try {
			//Reader는 char기반 스트림으로 읽어온다고 생각하면됨 
			//이미지파일이 아니기 때문에 2byte씩 읽어와도 문제없음
			Reader reader = 
				Resources.getResourceAsReader("config/mybatis/sqlMapConfig.xml");
			
			//위에서 읽어온 sqlMapConfig.xml에서 지정해둔 DB접근 경로를 실제로 읽어온다.
			//factory객체는 sqlMapConfig.xml에 있는 내용을 분석해서 갖고 있는다.
			factory = new SqlSessionFactoryBuilder().build(reader);
			reader.close();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//single-ton
	public static MyBatisConnector getInstance(){
		if(connector==null)
			connector = new MyBatisConnector();
		return connector;
	} //single-ton끝
	
	
	//sqlMapConfig.xml의 정보를 담고있는 factory객체를 반환 
	public SqlSessionFactory  getSqlSessionFactory()
	{
		return factory;
	}
}

Mybatis가 JDBC 대부분의 코드를 가지고있기 때문에 Mybatis만 가지고도 DB접속을 편리하게 할 수 있다.

SqlSession객체를 통해 DB작업을 진행하는데, 작업시 수행하는 쿼리는 mapper파일에 담겨있다.

 

Reader reader = Resources.getResourceAsReader("config/mybatis/sqlMapConfig.xml");

👉 sqlMapConfig.xml 파일을 문자열 형태로 읽어와서 reader 객체에 저장해두고 

 

factory = new SqlSessionFactoryBuilder().build(reader);

👉 SqlSessionFactoryBuilder 객체에 빌더메서드를 통해 우리가 읽어온 리더를 실제로 읽어서 factory객체에 저장하면 factory  객체는 DB까지 접근하는 경로를 알고 있다.

 

이것들은 public MyBatisConnector() 생성자 안에 존재하는데, 생성자는 객체 생성할 때 호출되는 것이므로

객체를 DAO에서 getInstance() 메서드를 호출했을 때 싱글톤패턴으로 최초1회 new MyBatisConnector(); 생성자가 호출된다.

그 다음부터 만들어진 return connector; 객체를 호출

 

그 뒤엔 factory  객체는 더이상 비어있지 않은 상태이므로 사용하기 위해 getSqlSessionFactory()메서드 생성 (getter와 비슷한역할?)

public SqlSessionFactory getSqlSessionFactory()

{

return factory;

}

 

 

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" />
			
			<!-- Mybatis 사용을 위해 JNDI를 찾아주는 코드 (context.xml을 찾아주는 코드)-->
			<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" />
	</mappers>
</configuration>

sqlMapConfig.xml의 의 개수와 mapper파일의 개수는 일치해야 한다.

 

 

dept.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>

 

 

DeptVO.java

package vo;

public class DeptVO {

	private int deptno;
	private String dname,loc;
	
	
	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 getLoc() {
		return loc;
	}
	public void setLoc(String loc) {
		this.loc = loc;
	}
	
	
}

 

 

DeptDAO.java

package dao;

import java.util.List;

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() { //기본생성자에서 MyBatisConnetor 호출하여 factory를 채워주자.
		factory = MyBatisConnector.getInstance().getSqlSessionFactory();
	}
	
	
	//부서테이블조회 
	public List<DeptVO> select(){
		//factory는 어떤 db로 연결하고 어떤 mapper로 접근해야하는지까지만 알고있다.
		//그 정보를 가지고 실제로 쿼리문을 요청하는 것은 SqlSession 객체가 한다. 
		SqlSession sqlsession = factory.openSession(); //sqlsession객체생성 
		
		//sqlSession에 있는 메서드는 이름을 막지으면 안됨 (dept.xml을 참고한다)
		//dept. ->식별자 mapper의 namespace
		//dept_list ->select태그의 id
		List<DeptVO> list = sqlsession.selectList("dept.dept_list");
		
		sqlsession.close(); //DB접근을 위해 사용한 sqlSession은 마지막에 닫는다.
		
		return list;
	}
	
}

 

 

DeptListAction.java

package action;

import java.io.IOException;

/**
 * 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 {
		// TODO Auto-generated method stub
		List<DeptVO> list = DeptDAO.getInstance().select(); //DAO호출
		
		//바인딩
		request.setAttribute("list", list);
		
		//포워딩
		RequestDispatcher disp = request.getRequestDispatcher("dept_list.jsp");
		disp.forward(request, response);
	}

}

 

 

dept_list.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 ="vo" items="${list}">
			<tr>
				<td>${vo.deptno}</td>	
				<td>${vo.dname}</td>	
				<td>${vo.loc}</td>		
			</tr>
			</c:forEach>
		</table>
	</body>
</html>

 

 

서블렛파일에서 실행

 

 


 

2️⃣사원테이블 만들기

위의 MyBatisConnector.java 그대로 사용

 

sawonVO.java

package vo;

public class SawonVO {

	private int sabun,sapay;
	private String saname, sajob, sahire;
	
	
	public int getSabun() {
		return sabun;
	}
	public void setSabun(int sabun) {
		this.sabun = sabun;
	}
	public int getSapay() {
		return sapay;
	}
	public void setSapay(int sapay) {
		this.sapay = sapay;
	}
	public String getSaname() {
		return saname;
	}
	public void setSaname(String saname) {
		this.saname = saname;
	}
	public String getSajob() {
		return sajob;
	}
	public void setSajob(String sajob) {
		this.sajob = sajob;
	}
	public String getSahire() {
		return sahire;
	}
	public void setSahire(String sahire) {
		this.sahire = sahire;
	}
	
	
}

 

 

sawonDAO.java

package dao;

import java.util.List;

public class SawonDAO {

	SqlSessionFactory factory;
	
	// single-ton pattern: 
	// 객체1개만생성해서 지속적으로 서비스하자
	static SawonDAO single = null;

	public static SawonDAO getInstance() {
		//생성되지 않았으면 생성
		if (single == null)
			single = new SawonDAO();
		//생성된 객체정보를 반환
		return single;
	}
	
	public SawonDAO() { //생성자
		factory = MyBatisConnector.getInstance().getSqlSessionFactory();
	}
	
	//사원테이블조회
	public List<SawonVO> select(){ //메서드
		SqlSession sqlSession = factory.openSession();
		List<SawonVO> list = sqlSession.selectList("sawon.sawon_list");
		
		sqlSession.close();
		
		return list; //반환하는 값의 타입과 일치해야함 List<SawonVO>
        		    //리턴하면 서블릿으로 감
	}

 

 

sawon.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="sawon">
<!-- mapper : DB에 쿼리문을 요청하고 결과를 돌려받는 속성파일 -->
 
<select id="sawon_list" resultType="vo.SawonVO"> <!-- select는 항상 resultType정해줘야함 패키지명.VO파일명-->
	SELECT * FROM SAWON <!-- 세미콜론 절대 금지 -->
</select>  

</mapper>

 

 

sqlMapConfig.xml 그대로 사용

...

<mappers>

<mapper resource="config/mybatis/mapper/dept.xml" /> <!-- 기존 -->

<mapper resource="config/mybatis/mapper/sawon.xml" /> <!-- 추가로 등록해줘야함 -->

</mappers>

 

 

SawonListAction.java

package action;

import java.io.IOException;

/**
 * Servlet implementation class SawonListAction
 */
@WebServlet("/sawon_list.do")
public class SawonListAction 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<SawonVO> list = SawonDAO.getInstance().select();
		
		//바인딩
		request.setAttribute("list", list);
		//포워딩
		RequestDispatcher disp = request.getRequestDispatcher("sawon_list.jsp");
		disp.forward(request, response);
	}

}

 

 

sawon_list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix ="c" uri="http://java.sun.com/jsp/jstl/core" %> <!-- 코어라이브러리 -->
<%@ taglib prefix ="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <!-- 자바함수사용가능 -->
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>Insert title here</title>
	</head>
	<body>
		<table border="1" align="center">
			<caption>:::사원목록:::</caption>
			<tr>
				<th>사번</th>
				<th>이름</th>
				<th>직책</th>
				<th>급여</th>
				<th>입사일</th>
			</tr>
		<c:forEach var="vo" items="${list}">
			<tr>
				<td>${vo.sabun}</td>
				<td>${vo.saname}</td>
				<td>${vo.sajob}</td>
				<td>${vo.sapay}</td>
				<c:set var = "sahire" value="${vo.sahire}"/>
				<td>${fn:split(sahire," ")[0]}</td>	<!-- 띄어쓰기 기준으로 나누고 0번째배열 가져오기 -->			
				<!-- <td>${vo.sahire}</td> --!> <!-- 날짜와 시간이 출력됨. 시간은 필요없으니 짤라보자 -->
			</tr>
		</c:forEach>
		</table>
	</body>
</html>

 

 

서블렛파일에서 실행

 

 

 


 

 

3️⃣고객테이블 만들기

위의 MyBatisConnector.java 그대로 사용

 

GogekVO.java

package vo;

public class GogekVO {

	private int gobun, godam;
	private String goname, goaddr, gojumin;
	
	public int getGobun() {
		return gobun;
	}
	public void setGobun(int gobun) {
		this.gobun = gobun;
	}
	public int getGodam() {
		return godam;
	}
	public void setGodam(int godam) {
		this.godam = godam;
	}
	public String getGoname() {
		return goname;
	}
	public void setGoname(String goname) {
		this.goname = goname;
	}
	public String getGoaddr() {
		return goaddr;
	}
	public void setGoaddr(String goaddr) {
		this.goaddr = goaddr;
	}
	public String getGojumin() {
		return gojumin;
	}
	public void setGojumin(String gojumin) {
		this.gojumin = gojumin;
	}
	
	
}

 

 

GogekDAO.java

package dao;

import java.util.List;

public class GogekDAO {

	SqlSessionFactory factory;
	
	// single-ton pattern: 
	// 객체1개만생성해서 지속적으로 서비스하자
	static GogekDAO single = null;

	public static GogekDAO getInstance() {
		//생성되지 않았으면 생성
		if (single == null)
			single = new GogekDAO();
		//생성된 객체정보를 반환
		return single;
	}
	
	public GogekDAO() { //생성자 
		factory = MyBatisConnector.getInstance().getSqlSessionFactory();
	}
	
	//고객테이블조회
	public List<GogekVO> select(){
		SqlSession sqlSession = factory.openSession();
		
		List<GogekVO> list = sqlSession.selectList("gogek.gogek_list");
		
		sqlSession.close();
		
		return list;
	}
	
}

 

 

Gogek.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="gogek">
<!-- mapper : DB에 쿼리문을 요청하고 결과를 돌려받는 속성파일 -->
 
<select id="gogek_list" resultType="vo.GogekVO"> <!-- select는 항상 resultType정해줘야함 패키지명.VO파일명-->
	SELECT * FROM GOGEK <!-- 세미콜론 절대 금지 -->
</select>  

</mapper>

 

 

sqlMapConfig.xml 그대로 사용

...

<mappers>

<mapper resource="config/mybatis/mapper/dept.xml" /> <!-- 기존 -->

<mapper resource="config/mybatis/mapper/sawon.xml" /> <!-- 기존 -->

<mapper resource="config/mybatis/mapper/gogek.xml" /> <!-- 추가로 등록해줘야함 -->

</mappers>

 

 

GogekListAction.java

package action;

import java.io.IOException;

/**
 * Servlet implementation class GogekListAction
 */
@WebServlet("/gogek_list.do")
public class GogekListAction 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<GogekVO> list = GogekDAO.getInstance().select();
		
		//바인딩
		request.setAttribute("list", list);
        	//포워딩
		RequestDispatcher disp = request.getRequestDispatcher("gogek_list.jsp");
		disp.forward(request, response);
	}

}

 

 

gogek_list.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" align="center">
			<caption>:::고객리스트:::</caption>
			<tr>
				<th>고객번호</th>
				<th>담당자</th>
				<th>이름</th>
				<th>주소</th>
				<th>주민번호</th>
			</tr>
			<c:forEach var="vo" items="${list}">
				<tr>
					<td>${vo.gobun}</td>
					<td>${vo.godam}</td>
					<td>${vo.goname}</td>
					<td>${vo.goaddr}</td>
					<td>${vo.gojumin}</td>
				</tr>
			</c:forEach>
		</table>
	</body>
</html>

 

 

서블렛파일에서 실행

 

 

 

 

728x90