MyBatis : 기초

부트캠프(END)/Web|2022. 7. 29. 17:35

MyBatis는 태그 형태의 코드로 간단하게 데이터베이스와 연결해 주도록 돕는 라이브러리이다!

 

사용해 보자.

https://github.com/mybatis/mybatis-3/releases

위 링크에서 zip파일 다운로드

 

zip파일의 압축을 풀고 파일 내의 모든 jar파일을 프로젝트 lib에 복사해 준다.

 

Eclipse의 상위 탭에서 "Help > Eclipse MarketPlace"

→ MyBatis 검색 및 설치

 

일반 xml파일로 Config.xml 을 만들고, MyBatis XML Mapper 파일로 board-mapper.xml을 만든다.

Config.xml은 데이터베이스와 연결하고 어떤 값을 어떻게 가져올 것인지 설정하는 파일,

board-mapper.xml은 실행할 쿼리 문장을 저장하는 곳이다.

 

 

아래와 같은 테이블에서 데이터를 가져온다고 해 보자.

 

 

 

1. Config.xml로 데이터베이스 연결 설정하기

xml파일에 이걸 추가해 주면 MyBatis가 제공하는 태그들을 다 볼 수 있도록 해준다.

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

위 코드를 추가하고 태그에 커서를 갖다 대면 아래와 같은 팝업이 표시된다.

configuration 태그 아래에 무슨 태그가 올 수 있는 지 보여주고 있음.

태그 작성 순서를 꼭 지켜야 한다. ex. setting 뒤에 properties 가 오면 안된다.

위 문서에서 볼 수 있듯이 특정 태그 아래에 올 수 있는 tag들은 태그명과 기호로 표기되어 있다.

 

각 기호는 아래와 같은 의미를 갖고 있다.

 

기호 의미
? 필요시에 사용하되 한 번만 사용이 가능하다.
* 0번 이상 여러 번 사용이 가능
+ 반드시 한 번 이상 사용해야 한다.
| 취사선택하여 사용한다.
default(없음) 반드시 한 번만 사용해야 한다.

 

데이터베이스 연결을 위해 <configuration> 태그 아래에 작성하는 태그

<typeAliases>

VO를 등록한다. 어떤 VO에서 값을 가져올 것인지 선택한다.

<environments>

연결 환경을 설정한다.

↳ <dataSource>

  DBCP를 사용할 것인지, JDBC를 사용할 것인지 선택한다.

 <properties>

  데이터베이스 정보를 저장한다! .properties라는 파일을 읽는다.  

<mappers>

  어떤 xml파일에서 SQL문을 읽어올 것인지 지정한다.

 

그렇게 작성한 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">
<!-- 
Connection 관련 내용이 저장되는 곳
getConnection()과 disConnection()이 만들어짐
 -->
<configuration>
   <typeAliases>
     <typeAlias type="doodoo.dao.MyBoardVO" alias="MyBoardVO"/> 
     <!-- SELECT문이 나가면 여기에 값을 채워 주세요 -->
   </typeAliases>
   <!-- 연결 설정 (getConnection, disConnection)-->
   <environments default="development"> <!--  (environment+) -->
     <environment id="development"> <!-- (transactionManager, dataSource) -->
       <transactionManager type="JDBC"/> <!-- AutoCommit 사용하겠다는 뜻 -->
       <dataSource type="POOLED">
         <!-- POOLED : DBCP / UNPOOLED : JDBC -->
          <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
          <property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
          <property name="username" value="user"/>
          <property name="password" value="pwd"/>
       </dataSource>
     </environment>
   </environments>
   <mappers>
   <!-- (mapper*, package*) -->
     <mapper resource="doodoo/dao/board-mapper.xml"/><!-- SQL문장 저장 위치 -->
   </mappers>
</configuration>

 

 

2. mapper.xml에서 실행할 쿼리문 작성하기

mapper.xml은 SQL문을 모아 저장한다.

마찬가지로 태그형태로 작성할 수 있다. 단, 태그 사이에 SQL 문장은 한 개만 설정해야 한다.

<select>, <insert>, <update>, <delete> 등 SQL문의 종류에 따라 태그를 정하고,

해당 태그 내에 기존 SQL문을 작성할 때처럼 작성하면 된다.

 

아래와 같이 id로 해당 SQL 문의 이름을 지어 주고,

resultType 과 parameterType이라는 속성을 지정할 수 있다.

 

<select id="" resultType="" parameterType="hashMap">

 

resultType은 select문에서만 사용할 수 있으며 어떤 형태로 결과를 받아올 지 정할 수 있다.

parameterType으로 WHERE 문에 들어갈 매개변수 타입을 지정할 수 있다.

기존의 SQL문에서 ? 에 들어갈 값의 타입을 지정한다고 보면 된다.

단, #{param} 과 같이 변수의 이름을 지정해 주고, 이후 DAO에서 실행할 때 값을 넣어 준다.

일반적인 parameterType으로는 한 번에 한 가지만 지정이 가능하므로

여러 개의 변수를 넣고 싶을 때에는 map을 활용해야 한다.

 

<sql id=""> 이라는 태그도 있는데, 공통 SQL을 묶어 사용한다. 예시로 보는 게 빠름!

 

 

 

board-mapper.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">
<!-- 테이블마다 있어야 함. ResultSet, PreparedStatement 관련 내용 -->
<mapper namespace="doodoo.dao.board-mapper">
<!-- SQL 문장 저장 -->
	<select id="boardListData" resultType="MyBoardVO">
		SELECT * FROM myBoard
	</select>
	<select id="boardCount" resultType="int">
		SELECT count(*) FROM myBoard
	</select>
</mapper>

 

 

3. DAO.java로 xml파일을 읽고 데이터 받아오기

Reader로 Config.xml 파일을 읽어 오면, Config.xml 내에 등록된 mapper파일도 함께 읽어 온다.

그리고 SqlSessionFactory로 Connection을 생성하고, session을 열어 쿼리문을 실행할 수 있다!

 

 

MyBoardDAO.java

package doodoo.dao;

import java.util.*;

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

import java.io.*;
public class MyBoardDAO {
  private static SqlSessionFactory ssf; //XML 읽는 역할
  static {
    try {
      //XML Parsing
      Reader reader = Resources.getResourceAsReader("Config.xml");
      ssf = new SqlSessionFactoryBuilder().build(reader);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }

  public static List < MyBoardVO > boardListData() {
    return ssf.openSession().selectList("boardListData"); //mapper에서 작성한 select 쿼리의 id
  }

  public static int boardCount() {
    return ssf.openSession().selectOne("boardCount"); //값을 하나만 받을 때는 selectOne
  }
}

 

데이터가 잘 나오는지 확인

MainClass.java

package doodoo.dao;

import java.util.List;

public class MainClass {

  public static void main(String[] args) {
    List < MyBoardVO > list = MyBoardDAO.boardListData();
    for (MyBoardVO vo: list) {
      System.out.println(vo.getNo() + "/" + vo.getName() + "/" + vo.getSubject());
    }

    int cnt = MyBoardDAO.boardCount();
    System.out.println(cnt + "개");
  }

}

 

 

 

MVC구조 프로젝트에 MyBatis 적용하기

추가로.. MVC구조를 가진 프로젝트에 MyBatis를 적용해서 화면에 출력까지 해 보자.

 

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>
	<typeAliases>
		<typeAlias type="doodoo.dao.BoardVO" alias="BoardVO"/>
	</typeAliases>
	<environments default="development"> <!-- 개발환경 만들기 -->
		<environment id="development">
			<transactionManager type="JDBC"/> <!-- AutoCommit을 쓰겠다. -->
			<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="user"/>
				<property name="password" value="pwd"/>
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="doodoo/mapper/board-mapper.xml"/>
	</mappers>
</configuration>

 

application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<component-scan base-package="doodoo.model"/>
</beans>

 

board-mapper.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="doodoo.mapper.board-mapper">

<select id="boardListData" resultType="BoardVO" parameterType="hashmap">
	SELECT no, subject, name, regdate, hit, num
	FROM (SELECT no, subject, name, regdate, hit, rownum as num
	FROM (SELECT /*+ INDEX_DESC(myBoard myb_no_pk)*/no, subject, name, regdate, hit
		  FROM myBoard))
	WHERE num BETWEEN #{start} AND #{end}
</select>
<sql id="where-no">
	WHERE no = #{no}
</sql>
<update id="boardHitIncrement" parameterType="int">
	UPDATE myBoard SET 
	hit = hit+1
	<include refid="where-no"/>
</update>

</mapper>

 

BoardVO.java (Class)

package doodoo.dao;

import java.util.Date;

/*
 * SELECT NVL(MAX(no)+1,1) as no FROM table 이런거 쓸때는 꼭 alias 써주어야 한다.
 */
public class BoardVO {
  private int no, hit;
  private String name, subject, content;
  private Date regdate;
  public int getNo() {
    return no;
  }
  public void setNo(int no) {
    this.no = no;
  }
  public int getHit() {
    return hit;
  }
  public void setHit(int hit) {
    this.hit = hit;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getSubject() {
    return subject;
  }
  public void setSubject(String subject) {
    this.subject = subject;
  }
  public String getContent() {
    return content;
  }
  public void setContent(String content) {
    this.content = content;
  }
  public Date getRegdate() {
    return regdate;
  }
  public void setRegdate(Date regdate) {
    this.regdate = regdate;
  }
}

 

BoardDAO.java (Class)

package doodoo.dao;

import java.util.*;

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 java.io.*;
public class BoardDAO {
  private static SqlSessionFactory ssf;
  static {
    //XML을 읽고 데이터를 주입시킨다.
    try {
      Reader reader = Resources.getResourceAsReader("Config.xml");
      ssf = new SqlSessionFactoryBuilder().build(reader);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }

  //목록보기
  public static List < BoardVO > boardListData(Map map) {
    //Map을 주고 #{start}와 #{end}에 값을 넣어줄 것임.
    SqlSession session = null; //SqlSession == Connection
    List < BoardVO > list = new ArrayList < BoardVO > ();
    try {
      session = ssf.openSession();
      list = session.selectList("boardListData", map);
    } catch (Exception ex) {
      ex.printStackTrace();
    } finally {
      session.close(); //반환
    }
    return list;
  }
}

 

BoardModel.java (Class)

package doodoo.model;

import java.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import controller.Controller;
import controller.RequestMapping;
import doodoo.dao.*;

@Controller
public class BoardModel {
  @RequestMapping("board/list.do")
  public String board_list(HttpServletRequest request, HttpServletResponse response) {
    String page = request.getParameter("page");
    if (page == null)
      page = "1";
    int curPage = Integer.parseInt(page);

    Map map = new HashMap();
    int start = (curPage * 10) - 9;
    int end = curPage * 10;

    map.put("start", start);
    map.put("end", end);

    List < BoardVO > list = BoardDAO.boardListData(map);
    request.setAttribute("list", list);

    return "../board/list.jsp";
  }
}

 

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="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<style type="text/css">
  *{
  
  }
  .container{
    margin-top:50px;
  }
  .row{
    margin: 0px auto;
    width: 960px;
  }
</style>
</head>
<body>
  <div class="container">
    <h1 class="text-center">MyBatis 게시판</h1>
    <div class="row">
      <table class="table">
        <tr class="warning">
          <th class="text-center" width=10%>번호</th>
          <th class="text-center" width=45%>제목</th>
          <th class="text-center" width=15%>이름</th>
          <th class="text-center" width=20%>작성일</th>
          <th class="text-center" width=10%>조회수</th>
        </tr>
        <c:forEach var="vo" items="${list }">
          <tr class="warning">
            <td class="text-center" width=10%>${vo.no }</td>
            <td width=45%>${vo.subject }</td>
            <td class="text-center" width=15%>${vo.name }</td>
            <td class="text-center" width=20%>
            <fmt:formatDate value="${vo.regdate }" pattern="yyyy-MM-dd"/></td>
            <td class="text-center" width=10%>${vo.hit }</td>
          </tr>
        </c:forEach>
        </table>
    </div>
  </div>
</body>
</html>

'부트캠프(END) > Web' 카테고리의 다른 글

JavaScript 기초 (1) : 변수, 연산자, 제어문  (0) 2022.08.01
MVC(2)  (0) 2022.07.28
MVC (1)  (0) 2022.07.27

댓글()