본문 바로가기
WEB/JSP

< myBatis + MVC + CRUD를 활용한 한 줄 메모장 만들기 - 01. 환경설정과 list출력

by 둥바 2022. 8. 10.

myBatis

- 이전에는 ibatis였으나 -> myBatis로 변경

- 개발자가 지정한 SQL, 저장프로시저를 지원하는 프레임워크(Java Persistence Framework)

예) 데이터베이스에 xml으로 쿼리문을 던져서 DB에서 처리하도록 

    비교) ORM(Object relational mapping)은 데이터베이스와 객체 지향 프로그래밍 언어간의 호환되지 않는 데이터를 변환 하는 프로그래밍 기법, 객체 관계 매핑

    ORM : 알아서 자동으로 SQL을 만든다(직접 작성할 필요 없음, 인간이 개입하는 비즈니스 부분까지 자동화)

- DAO 에 작성하던 SQL문을 분리하여 XML 파일에 별도로 작성

 

장점 )

- 유지보수 간편(XML파일의 SQL문만 변경하면 되므로)

- 코딩량 절감

 

구조)

Configuration - mapper(xml)이 쿼리문을 작동시켜서 데이터베이스에 주기도하고, 기타 필요한 객체에 값을 전달

이를 위해 SqlMapConfig.xml에서 설정 처리

 

설치)

myBatis도 라이브러리화 되어 있기 때문에, 해당 페이지에서 API를 다운로드 받아야 한다.

http://mybatis.org에 에 접속해 Products에 있는 myBatis압축파일을 다운로드 받는다.

 

설정방법)

1. mybatis-3.5.7.jar 파일을 WEB-INF/lib 폴더 아래에 복사한다.

2. MybatisManager.java : mybatis Framework를 실행할 수 있는 세션을 생성하는 코드 파일 작성

3. sqlMapConfig.xml : 실제 sql을 실행할 mapper파일을 이 xml파일에서 연동하여 환경설정

(mybatis 기본설정 파일)을 해야한다.

4. mapper.xml : 실제 sql 쿼리 문장

 

한 줄 메모장 (MVC 패턴)

<Controller>

MemoController.java - 서블릿

<Model>

MemoDTO.java 

MemoDAO.java

<View>

memo.jsp : ajax 요청 페이지, 메모입력

memo_list.jsp : 메모목록

memo_view.jsp : 메모 보기, 수정 , 삭제 기능

 

< CRUD의 기능을 구현 / 구현 흐름 >

1) 메모장 목록

list.do 요청 -> MemoController.java -> MemoDAO.java 로 전달 -> myBatis사용(xml 연동)-> 메모 리스트 리턴 -> request에 저장 -> memo_lis.jp로 포워딩

 

2) 메모 저장

insert.do 요청 -> MemoController.java -> MemoDAO.java 전달 -> xml파일 처리 -> memo.jsp로 이동

<태그 입력 변환>

메모장에 공백,태그문자 입력 시 html소스로 해석하지 못하도록 하기 위해 변환처리

 

3) 메모 수정

update.do(idx) -> 폼 입력 데이터를 DAO에 전달 -> update -> 수정완료 후 memo.jsp로 이동

 

4) 메모 삭제

delete.do(idx) -> 메모 번호를 dao로 전달 -> delete -> 삭제 완료 후 memo.jsp로 이동

 

 


MyBatis 환경 설정

 

1) sqlMapConfig.xml (myBatis 기본설정 파일) 먼저 작성

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

를 붙여넣기

<?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">
<!-- myBatis 환경설정 -->
<configuration>
	<!-- 알리아스 설정 : 리턴되는 데이터타입 알리아스 처리 -->
	<typeAliases>
	
	</typeAliases>
	<environments default="">
		<environment id="">
			<transactionManager type="JDBC"/>
			<dataSource type="JNDI">
				<!-- context.xml의 dbcp(DB커넥션 정보값)과 
				myBatis의 환경설정과 연결되어 있다. -->
				<property name="data_source" 
				value="java:comp/env/oraDB"/>
			</dataSource>
		</environment>
	</environments>
	
	<!-- 실제 sql query문 (xml을 만들어서 파일을 등록) -->
	<mappers>
	
	</mappers>
</configuration>

 

2) MybatisManager.java -> mybatis 실행할 수 있는 세션 생성

- 싱글톤 패턴을 통해, static 영역을 통해 공통으로 하나의 인스턴스만 생성하여 처리하여 서버의 부하를 줄인다.

- 생성자 private 처리

- SqlSessionFactoryBuilder.build(inputstream)로 빌드하여 SqlSessionFactory객체 얻음

public class MybatisManager {
	//Mybatis가 제공해주는 SqlSession객체 생성
	private static SqlSessionFactory instance;
	
	private MybatisManager() {
		/*생성자는 보통 public인데 private 처리
		 * -> 외부에서 접근이 안된다.
		 *웹프로그램 : 웹은 불특정 다수가 접속하여 서비스 받는다.
		 *MybatisManager m = new MybatisManager();
		 *을 실행하면 메모리가 늘어나고 결국은 서버가 다운되는 현상이 일어날 수 있다.
		 *다수의 인스턴스 생성을 막고 하나의 인스턴스만 생성시켜 처리한다.
		 *즉, 싱글톤 패턴
         *new해서 접근 불가, getInstance()로 우회해서 접근
		 */
	}
	
	public static SqlSessionFactory getInstance() {
		//메소드 생성(SqlSession 객체 반환)
		Reader reader = null;//Reader 객체
		try {
			//Reader 객체로 sqlmap 아래의 SqlMapConfig.xml(환경설정) 읽기
			reader = Resources.getResourceAsReader("sqlmap/sqlMapConfig.xml");
			//Reader로 설정정보 읽어서 SqlSessionFactory를 빌드
			instance = new SqlSessionFactoryBuilder().build(reader);
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if(reader!=null) {
					reader.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		
		return instance;
	}
}

파일을 불러오게 하기위해서 myBatis에서 제공하는 getResourceAsReader와 같은 메소드를 활용

*getResourceAsReader : Java Resource의 src의 xml을 읽어들이는 메소드

 

3)sqlDeveloper에서 한줄메모장.sql에서 필요한 부분 실행

 

select * from memo;

drop table memo;

--한줄 메모장 테이블 생성
create table memo (
idx number not null primary key,
writer varchar2(50) not null,
memo varchar2(300) not null,
post_date date default sysdate
);

-- 메모 추가
insert into memo(idx, writer, memo)
values (1, 'kim', '첫번째 메모');
insert into memo(idx, writer, memo)
values (2, 'park', '두번째 메모');

commit; -- 커밋 필수

select * from memo; --확인

 

_____________________ 여기까지 SQLDEVELOPER에서 실행


메모장 리스트 출력(select문) 

1) View 단인 memo.jsp 만들기

- id="result"인 div영역에 메모장 리스트를 출력할 것

- javascript와 ajax를 통해 "컨텍스트패스/memo_servlet/list.do" URL로 요청

- 이 자바스크립트 함수를 제이쿼리가 로딩하자마자 실행시켜줌

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>메모.jsp</title>
<%@ include file="../include/header.jsp" %>
<script src=../include/jquery-3.6.0.min.js></script>
<script type="text/javascript">
$(function(){
	//페이지 로딩되자마자 실행됨(제이쿼리)
	list();
});
//자바스크립트 처리
function list(){
	//ajax처리
	$.ajax({
		type: "post",//전송방식
		url: "${path}/memo_servlet/list.do",//요청URL
		success: function(result){//성공 시 콜백함수
			$("#result").html(result);
		}
			
	});
}


</script>
</head>
<body>
	<h2>한 줄 메모장</h2>
	<!-- 리스트 출력할 곳 -->
	<div id="result"></div>
</body>
</html>

 

2) 요청을 했으므로, 이 요청을 받아서 처리해줄 서블릿 틀 구현

 

package memo;

import java.io.IOException;
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("/memo_servlet/*")
//이렇게 요청이 들어오면 작동
public class MemoController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//사용자가 요청한 주소
		String uri = request.getRequestURI();
		System.out.println(uri);
		//만일 list.do 요청이 들어왔다면
		if(uri.indexOf("list.do") != -1) {
			
		}
		
	}

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

}

 

3) DAO,DTO 만들기

<여기서 잠깐! DAO,DTO 개념이 헷갈린다면 아주 간단하게 설명해주지.

사용자가 입력한 데이터를 DTO에 넣어서 전송해~ 이 DTO를 받은 서버는 DAO로 데이터베이스에 넣어주는 거지.

이것처럼 DTO는 데이터 교환을 위해 사용되는 객체, DAO는 데이터베이스에 접근하는 객체임을 잊지 말라고~>

 

 

3-1) DTO 클래스 memo.dto 패키지 아래에 만들기

(why?? 데이터베이스에 있는 데이터들을 담을 수 있는 클래스를 만들어야 DB에 있는 걸 가져오든지 말든지 할 거 아녀)

 

package memo.dto;


public class MemoDTO {
	private int idx;//인덱스번호
	private String writer;//작성자
	private String memo;//한 줄 메모
	private String post_date;//작성날짜
	
	//getter,setter,toString(),생성자2개
	
	public int getIdx() {
		return idx;
	}
	public void setIdx(int idx) {
		this.idx = idx;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getMemo() {
		return memo;
	}
	public void setMemo(String memo) {
		this.memo = memo;
	}
	public String getPost_date() {
		return post_date;
	}
	public void setPost_date(String post_date) {
		this.post_date = post_date;
	}
	@Override
	public String toString() {
		return "MemoDTO [idx=" + idx + ", writer=" + writer + ", memo=" + memo + ", post_date=" + post_date + "]";
	}
	public MemoDTO() {

	}
	public MemoDTO(int idx, String writer, String memo, String post_date) {
		this.idx = idx;
		this.writer = writer;
		this.memo = memo;
		this.post_date = post_date;
	}

}

 

3-2)DAO클래스 생성

 

package memo.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import memo.dto.MemoDTO;
import sqlmap.MybatisManager;

public class MemoDAO {
	
	
	//리스트를 받아오는 메소드 생성
	//myBatis에서는 ArrayList가 아닌 List를 쓰도록 고정되어 있다.
	public List<MemoDTO> listMemo(){
		//myBatis를 실행시키는 세션을 열어야 한다.
		SqlSession session = MybatisManager.getInstance().openSession();
		List<MemoDTO> list = null;
		//Mybatis도 하나의 리소스이기 때문에 try-catch문
		try {
			//select문 사용(리스트를 받아오므로)
			//selectList(네임스페이스.아이디)
			list = session.selectList("memo.listAll");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(session!=null) {
				session.close();//mybatis객체 닫기
			}
		}
		return list;
	}
}

 

4) mapper 생성 - memo.mapper 패키지 아래에 memo.xml 생성

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 붙여넣기

 

- mapper : namespace 속성

- select : id 속성과 resultType 속성

- 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="memo">
	<select id="listAll" resultType="memo.dto.MemoDTO">
	<!-- select 태그 : 반드시 반환해야하므로 resultType이 있음-->
	select idx,writer,memo,to_char(post_date,'yyyy-mm-dd hh24:mi:ss') post_date 
	from memo
	order by idx desc
	</select>
</mapper>

to_char(date,"원하는 형식") : 날짜를 원하는 형식으로 변경

-> 기존에는 dao쪽에 sql문을 적었으나, myBatis에서는 xml(mapper파일)에 따로 쿼리문을 작성하여 실행

단, dao에서 selectList("네임스페이스.아이디")로 연결

-> 따라서, sql문이 실행된 결과가 dto 형태로 호출한 쪽으로 반환

 

5)서블릿 쪽에서 마저 처리 진행

- list.do라는 요청이 들어온다면

- 생성한 dao 객체의 listMemo() 메소드를 실행 -> mapper로 sql 실행 -> 그 결과가 다시 list타입으로 저장

- 받아온 값(list)을 웹 영역에 저장하고 뷰 단으로 포워딩

package memo;

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 memo.dao.MemoDAO;
import memo.dto.MemoDTO;


@WebServlet("/memo_servlet/*")
//이렇게 요청이 들어오면 작동
public class MemoController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//사용자가 요청한 주소
		String uri = request.getRequestURI();
		System.out.println(uri);
		//DAO 객체 생성(dao의 메소드 사용을 위함)
		MemoDAO dao = new MemoDAO();
		//만일 list.do 요청이 들어왔다면
		if(uri.indexOf("list.do") != -1) {
			List<MemoDTO> list = dao.listMemo();
			//dao의 listMemo()실행하면,
				//마이바티스 생성
				//selectList로 매퍼 파일로 이동
				//select(쿼리)실행 //결과는 DTO로 받아(list)
				//호출한 dao.listMemo()로 반환
		
			//request(웹 영역)에 저장
			request.setAttribute("list", list);
			//포워딩(주소는 그대로, 화면 이동,대량 데이터)
			String page = "/memo/memo_list.jsp";
			RequestDispatcher rd = request.getRequestDispatcher(page);
			rd.forward(request, response);
		}
		
	}

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

}

 

6) mapper파일을 환경설정 config.xml에 등록해주어야 한다. (주의 - 잊어버리면 에러 발생 )

 <mappers>

      <mapper src="실제sql문이 들어있는 mapper의 파일 경로">

</mappers>

<?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">
<!-- myBatis 환경설정 -->
<configuration>
	<!-- 알리아스 설정 : 리턴되는 데이터타입 알리아스 처리 -->
	<typeAliases>
	
	</typeAliases>
	<!-- 핵심 설정 ) 트랜잭션 제어 + Connection 인스턴스를 가져오기 위한 DataSource -->
	<environments default="">
		<environment id="">
			<transactionManager type="JDBC"/>
			<dataSource type="JNDI">
				<!-- context.xml의 dbcp(DB커넥션 정보값)과 
				myBatis의 환경설정과 연결되어 있다. -->
				<property name="data_source" 
				value="java:comp/env/oraDB"/>
			</dataSource>
		</environment>
	</environments>
	
	<!-- 실제 sql query가 있는 매퍼파일 반드시 등록해야한다. 
	(xml을 만들어서 파일을 등록) -->
	<mappers>
		<mapper resource="/memo/mapper/memo.xml"/>
	</mappers>
</configuration>

 

7) 리스트를 출력해줄 memo_list.jsp를 만든다 - 뷰 단 만들기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<%@ include file="../include/header.jsp" %>
<script src=../include/jquery-3.6.0.min.js></script>
</head>
<body>
	<!-- 보낸 값들 idx,writer,memo,post_date 테이블로 출력-->
	<table border="1" width="500px">
		<tr>
			<th>번호</th>
			<th>이름</th>
			<th width="50%">메모</th>
			<th>날짜</th>
		</tr>
		<!-- JSTL을(확장된 for) 사용하여 list안에 있는 값들 뽑아오기 -->
		<c:forEach var="row" items="${list}">
			<tr>
				<td>${row.idx}</td>
				<td>${row.writer}</td>
				<td>${row.memo}</td>
				<td>${row.post_date}</td>
			</tr>
		</c:forEach>	
	
	</table>
</body>
</html>

 

< 실행 결과 >

 

'WEB > JSP' 카테고리의 다른 글

게시판 만들기 01. 게시판 목록 구현  (0) 2022.08.29
쿠키와 세션  (0) 2022.08.03
트랜잭션 처리, 배치 처리  (0) 2022.07.22
JDBC - DB연결해서 멤버 리스트 출력, 삽입, 삭제하기  (0) 2022.07.22
Session 객체  (0) 2022.07.18