spring - 마이바티스 프레임워크

오늘·2021년 6월 1일
0

웹 페이지 연습

목록 보기
23/35

등장 배경

기존의 JDBC 코드의 과정을 보면 복잡하다.
과정 : connection -> Statement 객체 생성 -> SQL문 전송 -> 결과 반환 -> close
이렇듯 SQL문이 프로그래밍 코드에 섞여 있는 모양이라 코드를 복잡하게 하고, 사용 및 유지 보수가 어렵게 만든다

마이바티스 프레임 워크는 SQL문의 가독성을 높여 사용이 편리하게끔 만들었다. 코드와 SQL문을 분리해 사용 및 유지 보수를 편리하게 한 것.

특징

  • SQL 실행 결과를 자바 빈즈 또는 Map 객체에 매핑해주는 Persisitance 솔루션으로 관리한다 -> 즉, SQL을 소스코드가 아닌 XML로 분리하는 것
  • SQL문과 프로그래밍 코드를 분리해서 구현한다
  • 데이터소스(DataSource) 기능과 트랜잭션 처리 기능을 제공한다.

실습해보기 01 - 회원정보 조회

마이 바티스 관련 설정 파일

  • SqlMapConfig.xml : 데이터 베이스 연동시 반환되는 값을 저장할 빈이나 트랜잭션, 데이터소스 등 마이바이스 관련 정보를 설정한다
  • member.xml : 회원 정보 관련 SQL문을 설정
  • 파일 모양 (SqlMapConfig는 myatis패키지에 / member.xml은 mybatis/mappers 패키지에 위치해있다)

SqlSession 클래스에서 제공하는 여러 메소드

1. SqlMapConfig.xml 작성

  • <dataSource> 태그를 이용해 마이바티스가 연동하는 DB에 대한 데이터 소스 설정
  • <mappers> 태그를 이용해 마이바이스에서 사용하는 SQL문이 있는 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>
	<!-- DAO에서 SQL문으로 값을 전달할 때
		또는 SQL문을 실행한 후 가져온 값을 DAO로 전달할 때 사용할 빈을 생성한다 -->
	<typeAliases>
		<!-- type : "위치" alias="사용할 것" -->
		<typeAlias type="com.spring.ex01.MemberVO" alias="memberVO" />
	</typeAliases>
	
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC"/>
			<!-- 마이바티스가 연동할 데이터베이스 연결 설정 -->
			<dataSource  type="POOLED">
				<property name="driver" value="oracle.jdbc.driver.OracleDriver" />
	            <property  name="url"    value="JDBC:oracle:thin:@localhost:1521:XE" />
    	        <property name="username" value="System" />
        	    <property name="password"  value="hb0317vd"/>   
			</dataSource>
		</environment>
	</environments>
		
	<!-- 회원 기능 관련 SQL문이 있는 member.xml을 읽어들이기 -->
	<mappers>
		<mapper resource="mybatis/mappers/member.xml" />
	</mappers>
</configuration>

2. member.xml 작성

  • <mapper namespace=""> : member.xml의 네임 스페이스슬 지정
  • <resultMape type="" id=""> : SQL문을 실행한 후 반환되는 레코드들을 SqlMapConfig.xml에서 typeAlias태그에 지정한 memberVO빈에 저장하겠다
  • <result property="" column=""> : 레코드의 컬럼 이름에 대해 memberVO와 같은 속성 값을 지정
  • <select id="" resultMap=""> : id는 DAO에서 id를 이용해 해당 SQL문을 호출하고 / resultMap은 반환되는 레코드를 memResult에 저장할 것이다.
<?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">
   
<!-- member.xml의 네임 스페이스 지정 -->
<mapper namespace="mapper.member">
	<!-- type
		: SQL문을 실행한 후 반환되는 레코드들을 TypeAlias태그에서 지정한 memberVO빈에 저장하겠다 -->
	<resultMap type="memberVO" id="memResult">
		<!-- 레코드의 컬럼 이름에 대해 memberVO와 같은 속성 값을 지정 -->
		<result property="id" column="id" />
		<result property="pwd" column="pwd" />
		<result property="name" column="name" />
		<result property="email" column="email" />
		<result property="joinDate" column="joinDate" />
	</resultMap>
	
	<!-- id : DAO에서 id를 이용해 해당 SQL문 호출 
		resultMap : 반환되는 레코드를 memResult에 저장 -->
	<select id="selectAllMemberList" resultMap="memResult">
		<![CDATA[ select * from t_member order by joinDate desc ]]>
	</select>
	
	
</mapper>

3. MemberServlet.java

  • 브라우저에서 요청하면 MemberDAO 객체를 생성한 후 selectAllMemberList()를 호출하는 서블릿
package com.spring.ex01;

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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/mem.do")
public class MemberServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
					throws ServletException, IOException {
		doHandle(request, response);
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
					throws ServletException, IOException {
		doHandle(request, response);
	}
	
	private void doHandle(HttpServletRequest request, HttpServletResponse response)
					throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html); charset=utf-8");
		
		// MemberDAO 객체를 생성하고
		MemberDAO dao = new MemberDAO();
		// selectAllMemberList()를 호출한다
		List membersList = dao.selectAllMemberList();
		
		request.setAttribute("memberList", membersList);
		RequestDispatcher dispatch =
				request.getRequestDispatcher("test01/listMembers.jsp");
		dispatch.forward(request, response);
	}
}

4. MemberDAO.java

  • SqlMapConfig.xml 파일을 이용해 SqlMapper 객체를 생성한다
    그 다음 select AllMemberList() 메소드를 호출해 인자로 mapper.member.selectAllMemberLsit 를 전달, member.xml 에서 해당 네임스페이스와 id에 해당하는 sql문을 실행한다.
package com.spring.ex01;

import java.io.Reader;
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 MemberDAO {
	private static SqlSessionFactory sqlMapper = null;
	public static SqlSessionFactory getInstance() {
		if(sqlMapper == null) {
			try {
				// MemberDAO의 각 메소드 호출 시 src/mybatis/SqlMapConfig.xml에서
				// 설정정보를 읽은 후 데이터베이스와의 연동을 준비한다
				String resouce = "mybatis/SqlMapConfig.xml";
				
				Reader reader = Resources.getResourceAsReader(resouce);
				
				// 마이바이스를 이용하는 sqlMapper 객체를 가져온다
				sqlMapper = new SqlSessionFactoryBuilder().build(reader);
				
				reader.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return sqlMapper;
	}
	
	public List<MemberVO> selectAllMemberList() {
		sqlMapper = getInstance();
		
		// 실제 member.xml의 SQL문을 호춣하는데 사용되는 sqlSession 객체를 가져온다
		SqlSession session = sqlMapper.openSession();
		
		List<MemberVO> memList = null;
		
		// 여러개의 레코드를 조회하기 때문에 selectList() 메소드에
		// 실행하고자 하는 SQL문 id를 인자로 전달해야 한다
		memList = session.selectList("mapper.member.selectAllMemberList");
		
		return memList;
	}
}

5. MemberVO.java

SQL문으로 전달할 값이나 SQL문을 실행한 후 반환되는 레코드들의 값을 각 속성에 저장합니다

package com.spring.ex01;

import java.sql.Date;

public class MemberVO {
	private String id;
	private String pwd;
	private String name;
	private String email;
	private Date joinDate;
	
	public MemberVO() {}
	public MemberVO(String id, String pwd, String name, String email) {
		this.id = id;
		this.pwd = pwd;
		this.name = name;
		this.email = email;
	}
	
	// 각 속성들의 getter와 setter
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public Date getJoinDate() {
		return joinDate;
	}
	public void setJoinDate(Date joinDate) {
		this.joinDate = joinDate;
	}
}

6. listMembers.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="UTF-8" isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<%  request.setCharacterEncoding("utf-8"); %>

<html>
<head>
<meta charset=utf-8">
<title>회원 정보 출력창</title>
</head>
<body>
	<table border="1" align="center" width="80%">
		<tr align="center" bgcolor="lightgreen">
			<td><b>아이디</b></td>
			<td><b>비밀번호</b></td>
			<td><b>이름</b></td>
			<td><b>이메일</b></td>
			<td><b>가입일</b></td>
		</tr>

		<c:forEach var="member" items="${membersList}">
			<tr align="center">
				<td>${member.id}</td>
				<td>${member.pwd}</td>
				<td>${member.name}</td>
				<td>${member.email}</td>
				<td>${member.joinDate}</td>

			</tr>
		</c:forEach>
	</table>
	<a href="${contextPath}/member/memberForm.do">
	<h1 style="text-align: center">회원가입</h1></a>
</body>
</html>

리스트 jsp를 실행하게 되면 테이블에 회원을 안 집어넣어 그런지 이런식으로 떴다.

그래서 오라클에 테이블을 만들어줬다.

create table t_member(
	id varchar(10) not null,
    pwd varchar(10) not null,
    name varchar(20),
    email varchar(20),
    joinDate date);

insert into t_member values ('a1', '123', '홍길동', 'aert@naver.com', to_date('2020/10/10') );
insert into t_member values ('a2', '456', '김유신', 'teadf@gmail.com', to_date('2020/8/7') );
insert into t_member values ('a3', '789', '이진아', 'qedc@naver.com', to_date('2019/11/16') );
insert into t_member values ('a4', '145', '곽용권', 'pijl@hanmail.com', to_date('2021/01/10') );
insert into t_member values ('a5', '243', '진홍섭', 'qekp@naver.com', to_date('2020/12/04') );
insert into t_member values('hong', '123','김유신','kim@naver.com',to_date('20/05/31') );

select * from t_member;

엥 근데 값을 넣어도 여전히 빈 표가 출력된다.
알고보니 오라클에서 테이블을 만들어준 후 커밋을 안해줘서.. 제대로 안나온거였음. commit까지 해주고 나니 아래와 같이 넣어준 값이 제대로 나왔다.


실습해보기 02 - 회원정보 조회

1. 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="mapper.member">
	<resultMap type="memberVO" id="memResult">
		<result property="id" column="id" />
		<result property="pwd" column="pwd" />
		<result property="name" column="name" />
		<result property="email" column="email" />
		<result property="joinDate" column="joinDate" />
	</resultMap>
	
	<select id="selectAllMemberList" resultMap="memResult">
		<![CDATA[
		select * from t_member order by joinDate desc
		]]>
	</select>
	
	<select id="selectName" resultType="String">
		<![CDATA[
		select name from t_member
		where id = 'hong'
		]]>
	</select>
	
	<select id="selectPwd" resultType="String">
		<![CDATA[
		select pwd form t_member
		where id='hong'
		]]>
	</select>
</mapper>

2. MemberServlet.java

package com.spring.ex02;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/mem2.do")
public class MemberServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response)	throws ServletException, IOException {
		doHandle(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}

	private void doHandle(HttpServletRequest request, HttpServletResponse response)	throws  ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		MemberDAO dao = new MemberDAO();
		
		String name = dao.selectName();
		PrintWriter pw = response.getWriter();
		
		pw.write("<script>");
		pw.write("alert(' 이름 : "+ name +"');");
		pw.write("</script>");

	}
}

3. MemberDAO.java

package com.spring.ex02;

import java.io.Reader;
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 MemberDAO {
	private static SqlSessionFactory sqlMapper = null;

	private static SqlSessionFactory getInstance() {
		if (sqlMapper == null) {
			try {
				String resource = "mybatis/SqlMapConfig.xml";
				Reader reader = Resources.getResourceAsReader(resource);
				sqlMapper = new SqlSessionFactoryBuilder().build(reader);
				reader.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return sqlMapper;
	}

	public String  selectName() {
		sqlMapper = getInstance();
		SqlSession session = sqlMapper.openSession();
		String name = session.selectOne("mapper.member.selectName");
		return name;
	} 
		
	public String selectPwd() {
		sqlMapper = getInstance();
		SqlSession session = sqlMapper.openSession();
		String pwd = session.selectOne("mapper.member.selectPwd");
		return pwd;
	}
}

실행해보니까.. 'hong'의 id에 해당하는 이름이 잘 출력되었다.


실습해보기 03 - 조건으로 회원 조회

마이바티스로 조건값 전달 방법

  • MemberDAO에서 메소드 호출 시 전달된 조건 값은, 매개변수 이름으로 SQL문의 조건식에 전달
  • SQL문에서 조건값 사용 방법 #{전달될 매개변수의 이름}

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="mapper.member">
	<resultMap type="java.util.HashMap" id="memResult">
		<result property="id" column="id" />
		<result property="pwd" column="pwd" />
		<result property="name" column="name" />
		<result property="email" column="email" />
		<result property="joinDate" column="joinDate" />
	</resultMap>
	
	<select id="selectAllMemberList" resultMap="memResult">
		<![CDATA[
		select * from t_member order by joinDate desc
		]]>
	</select>
	
	<!-- id : MemberDAO에서 호출하는 id 지정
		resultType : 조회되는 한 개의 레코드를 memberVO에 저장
		parameterType : MemberDAO에서 SQL문 호출시 전달되는 매개변수의 데이터 타입 지정 -->
	<select id="selectMemberById" resultType="memberVO" parameterType="String">
		<!-- MemberDAO에서 메소드를 호출하면 parameterType으로 전달된 매개변수 이름을
			select 문의 id 조건 값으로 사용한다 -->
		<![CDATA[
		select name from t_member
		where id = #{id}
		]]>
	</select>
	
	<select id="selectMemberByPwd" resultType="memResult" parameterType="String">
		<![CDATA[
		select pwd form t_member
		where id = #{pwd}
		]]>
	</select>
</mapper>

MemberServlet.java

브라우저의 요청에 대해 MemberDAO 클래스의 메소드를 호출, 그 결과를 브라우저로 출력하는 곳

package com.spring.ex03;

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 com.spring.ex01.MemberVO;

@WebServlet("/mem3.do")
public class MemberServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response)	throws ServletException, IOException {
		doHandle(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}

	private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		MemberDAO dao = new MemberDAO();
		MemberVO memberVO = new MemberVO();
		String action = request.getParameter("action");
		String nextPage = "";

		if (action== null || action.equals("listMembers")) {
			List<MemberVO> membersList = dao.selectAllMemberList();
			request.setAttribute("membersList", membersList);
			nextPage = "test02/listMembers.jsp";
			
		// 검색 조건이 selectMemberById이면 전송된 값을 getParameter()로 가저온 후
		// SQL문의 조건식에서 id의 조건 값으로 전달
		} else if (action.equals("selectMemberById")) {
			String id = request.getParameter("value");
			memberVO = dao.selectMemberById(id);
			request.setAttribute("member", memberVO);
			nextPage = "test02/memberInfo.jsp";
			
		// 검색 조건이 selectMemberByPwd이면 전송된 값을
		// getParmeter()로 가져온 후 sql문의 조건식 pwd의 조건값으로 전달
		} else if (action.equals("selectMemberByPwd")) {
			String pwd = request.getParameter("value");
			List<MemberVO> membersList = dao.selectMemberByPwd(pwd);
			request.setAttribute("membersList", membersList);
			nextPage = "test02/listMembers.jsp";
		}
		
		RequestDispatcher dispatch = request.getRequestDispatcher(nextPage);  
		dispatch.forward(request, response);
	}
}

MemberDAO.java

selectOne() 메소드는 하나의 레코드를 조회할 때 사용한다. 두 번째 인자는 첫번째 인자의 sql문에서 매개변수 이름 id로 조건값을 전달

package com.spring.ex03;

import java.io.Reader;
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;

import com.spring.ex01.MemberVO;

public class MemberDAO {
	public static SqlSessionFactory sqlMapper = null;

	private static SqlSessionFactory getInstance() {
		if (sqlMapper == null) {
			try {
				String resource = "mybatis/SqlMapConfig.xml";
				Reader reader = Resources.getResourceAsReader(resource);
				sqlMapper = new SqlSessionFactoryBuilder().build(reader);
				reader.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return sqlMapper;
	}

	public List<MemberVO> selectAllMemberList() {
		sqlMapper = getInstance();
		SqlSession session = sqlMapper.openSession();
		List<MemberVO> memlist = null;
		memlist = session.selectList("mapper.member.selectAllMemberList");
		return memlist;
	}


	public MemberVO selectMemberById(String id) {
		sqlMapper = getInstance();
		SqlSession session = sqlMapper.openSession();

		// selectOne : 레코드 하나만 조회할 때 사용
		// selectOne(인자1, 인자2) : 인자2는 서블릿에서 넘어온 id의 값을 메소드 호출 시 해당 sql 문의 조건값으로 전달
		MemberVO memberVO = session.selectOne("mapper.member.selectMemberById", id);
		return memberVO;
	}

	

	public List<MemberVO> selectMemberByPwd(String pwd) {
		sqlMapper = getInstance();
		SqlSession session = sqlMapper.openSession();
		List<MemberVO> membersList = null;
		
		// selectList : 말 그대로 list로 저장하겠다. 비밀번호가 같은 회원은 여러명일 수도 있으니까
		membersList = session.selectList("mapper.member.selectMemberByPwd", pwd);
		return membersList;
	}
}

search.jsp

검색창에 입력한 값과 셀렉트 박스의 검색 조건을 선택해 서블릿으로 전송

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isELIgnored="false"  %>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"  %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>회원 검색 창</title>
</head>
<body>
	<form action="${pageContext.request.contextPath}/mem3.do">
		입력 : <input type="text" name="value" />
		<select name="action">
			<option value="listMembers"> 전체 </option>
			<option value="selectMemberById"> 아이디 </option>
			<option value="selectMemberByPwd"> 비밀번호 </option>
		</select>
		<br>
		<input type="submit" value="검색" />
	</form>
</body>

memberinfo.jsp

검색 조건으로 조회한 회원 정보 출력

<%@ page language="java" contentType="text/html; charset=UTF-8"
	import="java.io.*,java.util.*" pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>    
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>회원 정보 출력</title>
</head>
<body>
	<table border="1" align="center" width="100%">
		<tr align="center" bgcolor="lightgreen">
			<td><b>아이디</b></td>
			<td><b>비밀번호</b></td>
			<td><b>이름</b></td>
			<td><b>이메일</b></td>
			<td><b>가입일</b></td>
		</tr>
		
		<tr align="center">
			<td>${member.id}</td>
			<td>${member.pwd}</td>
			<td>${member.name}</td>
			<td>${member.email}</td>
			<td>${member.joinDate}</td>
		</tr>
	</table>
</body>
</html>

0개의 댓글