MyBatis의 소개와 설정

 

1. MyBatis란?

 

SQL Mapping Framework - Easy & Simple

자바 코드로부터 SQL문을 분리해서 관리

매개변수 설정과 쿼리 결과를 읽어오는 코드를 제거

작성할 코드가 줄어서 생산성 향상 & 유지 보수 편리

 

2. SqlSessionFactoryBean과 SqlSessionTemplate

 

SqlSessionFactory - SqlSession을 생성해서 제공

SqlSession - SQL 명령을 수행하는데 필요한 메소드 제공

 

(둘 다 인터페이스이며 mybatis에서 제공)

(root-context.xml에 두 인터페이스의 빈을 등록해야함)

 

SqlSessionFactoryBean - SqlSessionFactory를 Spring에서 사용하기 위한 빈 (mybatis-spring에서 제공)

SqlSessionTemplate - SQL 명령을 수행하는데 필요한 메소드 제공. thread-safe

(SqlSessionTemplate를 여러 Dao에서 공유해서 쓸 수 있음. 멀티쓰레드에 안전함)

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
   <property name="dataSource" ref="dataSource"/>
   <property name="configLocation"  value="classpath:mybatis-config.xml"/>
   <property name="mapperLocations" value="classpath:mapper/*Mapper.xml"/>
</bean>

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
   <constructor-arg ref="sqlSessionFactory"/>
</bean>

(4번째 줄에서 *Mapper.xml 위치를 지정해줘야 함)

 

 

 

3. SqlSession의 주요 메소드

한 행(row)를 가져올 땐 selectOne

여러 행을 가져올 땐 selectList, selectMap 을 사용. 보통 List를 많이 사용함

 

Object parameter는 넘겨줄 값이 담긴 객체인데, User 객체에 담아서 주거나 Map에 담아서 주면 된다.

넘겨줄 값이 없으면 parameter 없이 줌.

 

 

 

4. Mapper XML의 작성

 

 

[ boardMapper.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="com.fastcampus.ch4.dao.BoardMapper">
    <select id="count" resultType="int">
        SELECT count(*) FROM board
    </select>

    <delete id="deleteAll">
        DELETE FROM board
    </delete>

    <delete id="delete" parameterType="map">
        DELETE FROM board WHERE bno = #{bno} and writer = #{writer}
    </delete>

    <insert id="insert" parameterType="BoardDto">
        INSERT INTO board
            (title, content, writer)
        VALUES
            (#{title}, #{content}, #{writer})
    </insert>

    <select id="selectAll" resultType="BoardDto">
        SELECT bno, title, content, writer, view_cnt, comment_cnt, reg_date
        FROM board
        ORDER BY reg_date DESC, bno DESC
    </select>

    <sql id="selectFromBoard">
        SELECT bno, title, content, writer, view_cnt, comment_cnt, reg_date
        FROM board
    </sql>

    <select id="select" parameterType="int" resultType="BoardDto">
        <include refid="selectFromBoard"/>
        WHERE bno = #{bno}
    </select>

    <select id="selectPage" parameterType="map" resultType="BoardDto">
        <include refid="selectFromBoard"/>
        ORDER BY reg_date DESC, bno DESC
        LIMIT #{offset}, #{pageSize}
    </select>

    <update id="update" parameterType="BoardDto">
        UPDATE board
        SET   title = #{title}
          , content = #{content}
          , up_date = now()
        WHERE bno = #{bno}
    </update>

    <update id="updateCommentCnt" parameterType="map">
        UPDATE board
        SET   comment_cnt = comment_cnt + #{cnt}
        WHERE bno = #{bno}
    </update>

    <update id="increaseViewCnt" parameterType="int">
        UPDATE board
        SET   view_cnt = view_cnt + 1
        WHERE bno = #{bno}
    </update>

</mapper>
public String getServerTime() throws Exception {
	return session.selectOne(namespace+"now");
} // T selectOne(String statement)

boardMapper.xml에 등록된, namespace가 일치하고 id="now" 인 sql문을 실행함.

 

boardMapper.xml에서

 

resultType은 반환 타입을 의미함.

반환 타입이 항상 일정하면 resultType을 생략할 수 있음.

(예를 들면 id="insert"의 경우, insert는 항상 int를 반환하므로 생략되는 것을 볼 수 있음)

 

parameterType은 입력으로 들어가는 값이 담긴 클래스 객체를 의미함.

해당 클래스의 getter 메소드를 이용하기 때문에, 클래스 객체를 주면 필요한 값들을 자동으로 입력하게 된다.

 

id="select"의 경우 parameterType이 int(원래는 Integer, 별명이 int임)인데,

위 예제의 경우 게시물 번호를 의미하기 때문에 게시물 번호를 입력하면 BoardDto의 해당 select 값들을 얻을 수 있음.

 

 

5. <typeAliases>로 이름 짧게 하기 - https://mybatis.org/mybatis-3/configuration.html#typeAliases 

 

<typeAliases>
	<typeAlias alias="BoardDto" type="com.fastcampus.ch4.domain.BoardDto"/>
<typeAliases>

Integer를 int라는 별명으로 사용하듯이

별명을 직접 만들어서 사용할 수 있음.

별명은 대소문자 구별이 없음. 대문자나 소문자나 같음.

 

 

MyBatis로 DAO작성하기

1. BoardDao의 작성

 

1) DB테이블 생성

2) Mapper XML & DTO 작성

3) DAO 인터페이스 작성

4) DAO 인터페이스 구현 & 테스트

 

2. DTO란? Data Transfer Object

 

계층간의 데이터를 주고 받기 위해 사용되는 객체

 

 

 

3. #{}와 ${}의 차이

 

#{} 는 PreparedStatement를 쓰고 (VALUES의 ? 값에만 사용할 수 있음)

${} 는 Statement를 씀 (sql문 전체에 사용 가능)

 

 

4. XML의 특수 문자 처리

XML내의 특수 문자 (<, >, &, ...)는 &lt; &gt;로 변환 필요

또는 특수문자가 포함된 쿼리를 <![CDATA[    내용   ]]> 으로 감싼다

 

package com.fastcampus.ch4.dao;

import com.fastcampus.ch4.domain.BoardDto;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Repository
public class BoardDaoImpl implements BoardDao {
    @Autowired
    SqlSession session;

    String namespace = "com.fastcampus.ch4.dao.BoardMapper.";

    @Override
    public int count() throws Exception {
        return session.selectOne(namespace+"count");
    } // T selectOne(String statement)

    @Override
    public int deleteAll() {
        return session.delete(namespace+"deleteAll");
    } // int delete(String statement)

    @Override
    public int delete(Integer bno, String writer) throws Exception {
        Map map = new HashMap();
        map.put("bno", bno);
        map.put("writer", writer);
        return session.delete(namespace+"delete", map);
    } // int delete(String statement, Object parameter)

    @Override
    public int insert(BoardDto dto) throws Exception {
        return session.insert(namespace+"insert", dto);
    } // int insert(String statement, Object parameter)

    @Override
    public List<BoardDto> selectAll() throws Exception {
        return session.selectList(namespace+"selectAll");
    } // List<E> selectList(String statement)

    @Override
    public BoardDto select(Integer bno) throws Exception {
        return session.selectOne(namespace + "select", bno);
    } // T selectOne(String statement, Object parameter)

    @Override
    public List<BoardDto> selectPage(Map map) throws Exception {
        return session.selectList(namespace+"selectPage", map);
    } // List<E> selectList(String statement, Object parameter)

    @Override
    public int update(BoardDto dto) throws Exception {
        return session.update(namespace+"update", dto);
    } // int update(String statement, Object parameter)

    @Override
    public int increaseViewCnt(Integer bno) throws Exception {
        return session.update(namespace+"increaseViewCnt", bno);
    } // int update(String statement, Object parameter)
    
}

boardMapper.xml 에 등록한 sql문을 활용하여 BoardDaoImpl 클래스를 만들었다.

 

이렇게 만든 BoardDao를 활용하여 Service를 만든다.

package com.fastcampus.ch4.service;

import com.fastcampus.ch4.dao.*;
import com.fastcampus.ch4.domain.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;

import java.util.*;

@Service
public class BoardServiceImpl implements BoardService {
    @Autowired
    BoardDao boardDao;

    @Override
    public int getCount() throws Exception {
        return boardDao.count();
    }

    @Override
    public int remove(Integer bno, String writer) throws Exception {
        return boardDao.delete(bno, writer);
    }

    @Override
    public int write(BoardDto boardDto) throws Exception {
        return boardDao.insert(boardDto);
    }

    @Override
    public List<BoardDto> getList() throws Exception {
        return boardDao.selectAll();
    }

    @Override
    public BoardDto read(Integer bno) throws Exception {
        BoardDto boardDto = boardDao.select(bno);
        boardDao.increaseViewCnt(bno);

        return boardDto;
    }

    @Override
    public List<BoardDto> getPage(Map map) throws Exception {
        return boardDao.selectPage(map);
    }

    @Override
    public int modify(BoardDto boardDto) throws Exception {
        return boardDao.update(boardDto);
    }

}

출처 : 스프링의 정석 : 남궁성과 끝까지 간다

+ Recent posts