๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Spring/Spring Quick Start

Mybatis ํ”„๋กœ์ ํŠธ

 

Spring Quick Start(์ฑ…)์˜ Day5 class01~02 ์‹ค์Šต์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ ๊ธฐ๋กํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

์‹ค์Šตํ•œ ์ฝ”๋“œ์˜ ๋งํฌ์ž…๋‹ˆ๋‹ค.


Mybatis ํ”„๋ ˆ์ž„์›Œํฌ์˜ ์ค‘์š”ํ•œ ํŠน์ง•

  1. ํ•œ ๋‘์ค„์˜ ์ž๋ฐ” ์ฝ”๋“œ๋กœ dB ์—ฐ๋™์„ ์ฒ˜๋ฆฌํ•œ๋‹ค

  2. SQL ๋ช…๋ น์–ด๋ฅผ java ์ฝ”๋“œ์—์„œ ๋ถ„๋ฆฌํ•˜์—ฌ XML ํŒŒ์ผ์— ๋”ฐ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค.

Mybatis ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ Data Mapper๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

Mybatis๋Š” xmL ํŒŒ์ผ์— ์ €์žฅ๋œ SQL ๋ช…๋ น์–ด๋ฅผ ๋Œ€์‹  ์‹คํ–‰ํ•˜๊ณ  ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ VO ๊ฐ™์€ ๊ฐ์ฒด์— ์ž๋™์œผ๋กœ ๋งคํ•‘๊นŒ์ง€ ํ•ด์ค€๋‹ค.


====Mybatis ํ”„๋กœ์ ํŠธ ์ž‘์„ฑ๋ฐฉ๋ฒ•====

1. pom.xml์— dependency ๋“ฑ๋กํ•˜๊ธฐ

<!-- MySQL -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.21</version>
</dependency>
<!-- Mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
</dependency>
<!-- Ibatis -->
<dependency>
    <groupId>org.apache.ibatis</groupId>
    <artifactId>ibatis-core</artifactId>
    <version>3.0</version>
</dependency>

2. VO ํด๋ž˜์Šค ์ž‘์„ฑํ•˜๊ธฐ

XML ํŒŒ์ผ์— ์ €์žฅ๋œ SQL ๋ช…๋ น์–ด์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’๋“ค์„ ์ „๋‹ฌํ•˜๊ณ  ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ๋งคํ•‘ํ•˜๋Š”๋ฐ ์“ฐ์ธ๋‹ค.

package com.springbook.biz.board;

import java.util.Date;

public class BoardVO {
	private int seq;
	private String title;
	private String writer;
	private String content;
	private Date regDate;
	private int cnt;
	private String searchCondition;
	private String searchKeyword;

	// getter, setter, toString
}

3. SQL Mapper XML ํŒŒ์ผ ์ž‘์„ฑํ•˜๊ธฐ

SQL Mapper XML์€ DB ์—ฐ๋™์— ํ•„์š”ํ•œ SQL ๋ช…๋ น์–ด๋“ค์ด ์ €์žฅ๋˜๋Š” Mybatis์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํŒŒ์ผ์ด๋‹ค.

SQL๋ฌธ์€ ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ถ„ํ•˜์ง€ ์•Š๋Š”๋ฐ ์‹๋ณ„์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด ์ผ๋ฐ˜์ ์œผ๋กœ ๋Œ€๋ฌธ์ž๋กœ ์ž‘์„ฑํ•œ๋‹ค.

[resource/mappings/board-mapping.xml]

<mapper namespace="BoardDAO">
    <insert id="insertBoard1">
		SET @mymax := (SELECT MAX(SEQ) FROM BOARD);
	</insert>
    <insert id="insertBoard2">
		INSERT INTO BOARD(SEQ, TITLE, WRITER, CONTENT)
		VALUES (IFNULL(@mymax, 0)+1,#{title},#{writer},#{content});
	</insert>

    <update id="updateBoard">
		UDDATE BOARD SET TITLE=#{title}, CONTENT=#{content} WHERE SEQ=#{seq}
	</update>

    <delete id="deleteBoard">
		DELETE BOARD WHERE SEQ=#{seq}
	</delete>

    <select id="getBoard" resultType="board">
		SELECT * FROM BOARD WHERE SEQ=#{seq}
	</select>

    <select id="getBoardList" resultType="board">
		SELECT * FROM BOARD
		WHERE TITLE LIKE '%'||#{searchKeyword}||'%'
		ORDER BY SEQ DESC
	</select>
</mapper>

1์ค„: ๋‚˜๋Š” xml ํŒŒ์ผ์ด๋‹ค.

2์ค„: DTD ์„ ์–ธ์ด๋‹ค.

 

<mapper>: ๋ฃจํŠธ ์—˜๋ฆฌ๋จผํŠธ์ด๊ณ  namespace ์†์„ฑ์œผ๋กœ DAO ํด๋ž˜์Šค์—์„œ ์ฐธ์กฐํ•  ๋•Œ ์ด ๊ฐ’์„ ์“ด๋‹ค.

 

<select>์˜ ์†์„ฑ์—๋Š” id, parameterType, resultType์ด ์žˆ๋‹ค.

  • id: ํ•„์ˆ˜ ์†์„ฑ์œผ๋กœ <mapper>์˜ namespace ๊ฐ€ ๊ฐ™์€ ํŒŒ์ผ "์•ˆ"์—์„œ ์œ ์ผํ•œ ์•„์ด๋””๋ฅผ ๋“ฑ๋กํ•ด์•ผ ํ•œ๋‹ค.

  • parameterType: sql ์‹คํ–‰์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์™ธ๋ถ€๋กœ๋ถ€ํ„ฐ ๋ฐ›์•„์•ผํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

    • parameterType="com.springbook.biz.board.BoardVO" ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  ์œ„์™€ ๊ฐ™์ด #{๋ณ€์ˆ˜๋ช…} ์‚ฌ์šฉ์ž ์ž…๋ ฅ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

    • ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฑด parameterType ์†์„ฑ์€ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋Œ€๋ถ€๋ถ„ ์ƒ๋žตํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

  • resultType: ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋กœ ResultSet์ด ๋ฆฌํ„ด๋˜๋Š”๋ฐ, ์–ด๋–ค ์ž๋ฐ” ๊ฐ์ฒด์— ๋งคํ•‘ํ• ์ง€ ์ง€์ •ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ์—์„œ resultType="board"๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ด์œ ๋Š” sql-map-config.xml ํŒŒ์ผ์—์„œ alias๋กœ ๋“ฑ๋กํ•ด๋†“์•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

<insert> ๊ตฌ๋ฌธ์€ ์ž์‹ ์š”์†Œ๋กœ <selectKey>๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ๊ธฐ๋ณธ ํ‚ค ํ•„๋“œ๋ฅผ ์‰ฝ๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ํ•˜๋‚˜์˜ ์ž๋ฐ” ๊ฐ์ฒด๋กœ ๋งคํ•‘ํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ์— ( ์˜ˆ๋ฅผ ๋“ค๋ฉด JOIN ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•  ๋•Œ) mapper ๋ฐ‘์— <resultMap>์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งคํ•‘ ๊ทœ์น™์„ ์ง€์ •ํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

SQL ์•ˆ์—์„œ "WHERE SEQ < #{seq}" ์™€ ๊ฐ™์ด ๋ถ€๋“ฑํ˜ธ๋ฅผ ์“ฐ๊ณ  ์‹ถ๋‹ค๋ฉด CDATA Section์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

 

4. Mybatis ๋ฉ”์ธ ํ™˜๊ฒฝ์„ค์ • ํŒŒ์ผ ์ž‘์„ฑํ•˜๊ธฐ

[resource/sql-map-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>
	<!-- Properties ํŒŒ์ผ ์„ค์ • -->
	<properties resource="db.properties" />
	<!-- Alias ์„ค์ • -->
	<typeAliases>
		<typeAlias alias="board" type="com.springbook.biz.board.BoardVO" />
	</typeAliases>
	<!-- DataSource ์„ค์ • -->
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driverClassName}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<!-- Sql Mapper ์„ค์ • -->
	<mappers>
		<mapper resource="mappings/board-mapping.xml" />
	</mappers>
</configuration>

 

5. db.properties ํŒŒ์ผ ์ž‘์„ฑํ•˜๊ธฐ

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜ ๊ด€๋ฆฌ ํ”„๋กœํผํ‹ฐ ์ •๋ณด๊ฐ€ ๋“ค์–ด์žˆ๋Š” ํŒŒ์ผ์ด๋‹ค.

[resource/db.properties]

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springquickstart?serverTimezone=Asia/Seoul&useSSL=false&allowPublicKeyRetrieval=true
jdbc.username=jueun
jdbc.password=jueun

6. SqlSession ๊ฐ์ฒด ์ƒ์„ฑํ•˜๊ธฐ

Mybatis๋ฅผ ์ด์šฉํ•˜์—ฌ DAO๋ฅผ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด SqlSession ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

๋˜ SqlSession ๊ฐ์ฒด๋ฅผ ์–ป์œผ๋ ค๋ฉด SqlSessionFactory ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

package com.springbook.biz.util;

import java.io.Reader;

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 SqlSessionFactoryBean {
	private static SqlSessionFactory sessionFactory = null;
	static {
		try {
			if (sessionFactory == null) {
				// ์—ฌ๊ธฐ๊ฐ€ ํ•ต์‹ฌ์ฝ”๋“œ
				// sql-map-config.xml์—์„œ ์„ค์ • ์ •๋ณด๋ฅผ ์ฝ์–ด๋“ค์ด๊ธฐ ์œ„ํ•˜ ์ž…๋ ฅ ์ŠคํŠธ๋ฆผ์„ ์ƒ์„ฑํ•˜๊ณ 
				// ์ด ์ž…๋ ฅ ์ŠคํŠธ๋ฆผ์„ ํ†ตํ•ด SqlSessionFactory ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
				Reader reader = Resources.getResourceAsReader("sql-map-config.xml");
				sessionFactory = new SqlSessionFactoryBuilder().build(reader);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static SqlSession getSqlSessionInstance() {
		return sessionFactory.openSession();
	}
}

7. DAO ํด๋ž˜์Šค ์ž‘์„ฑํ•˜๊ธฐ

SqlSession ๊ฐ์ฒด๋Š” Mapper XML์— ๋“ฑ๋ก๋œ SQL์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๋‹ค์–‘ํ•œ API๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

selectOne(), selectList(), insert(), update(), delete() ๋ฉ”์†Œ๋“œ์ด๋‹ค.

package com.springbook.biz.board.impl;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.util.SqlSessionFactoryBean;

public class BoardDAO {
	private SqlSession mybatis;

	public BoardDAO() {
		mybatis = SqlSessionFactoryBean.getSqlSessionInstance();
	}

	public void insertBoard(BoardVO vo) {
		mybatis.insert("BoardDAO.insertBoard", vo);
		mybatis.commit();
	}

	public void updateBoard(BoardVO vo) {
		mybatis.update("BoardDAO.updateBoard", vo);
		mybatis.commit();
	}

	public void deleteBoard(BoardVO vo) {
		mybatis.delete("BoardDAO.deleteBoard", vo);
		mybatis.commit();
	}

	public BoardVO getBoard(BoardVO vo) {
		return (BoardVO) mybatis.selectOne("BoardDAO.getBoard", vo);
	}

	public List<BoardVO> getBoardList(BoardVO vo) {
		return mybatis.selectList("BoardDAO.getBoardList", vo);
	}
}

8. ํ…Œ์ŠคํŠธํ•ด๋ณด๋Š” ํด๋ผ์ด์–ธํŠธ ์ž‘์„ฑํ•ด์„œ ์‹คํ–‰ํ•ด๋ณด๊ธฐ

main > test ํด๋” ๋ฐ‘์— ํ•ด๋‹นํ•œ๋‹ค.

package com.springbook.biz.board;

import com.springbook.biz.board.impl.BoardDAO;

import java.util.List;

public class BoardServiceClient {
    public static void main(String[] args) {
        BoardDAO boardDAO = new BoardDAO();

        BoardVO vo = new BoardVO();
        vo.setTitle("myBatis ์ œ๋ชฉ");
        vo.setWriter("ํ™๊ธธ๋™");
        vo.setContent("myBatis ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค......");
        boardDAO.insertBoard(vo);

        vo.setSearchCondition("TITLE");
        vo.setSearchKeyword("");
        List<BoardVO> boardVOList = boardDAO.getBoardList(vo);
        for (BoardVO board: boardVOList)
            System.out.println("---> " + board.toString());
    }
}

๋ฐ‘์€ ์ž˜ ์‹คํ–‰๋œ ํ™”๋ฉด์ด๋‹ค.

์ถœ๋ ฅ ๊ฒฐ๊ณผ