본문 바로가기

Spring

ch4 01. MyBatis의 소개와 설정

1.  MyBatis란?

- SQL Mapping Framework - Easy & Simple

SQL Mapping이라는 말은 Java 코드와 SQL을 매핑해준다는 뜻이다. 
SQL을 별도 xml으로 분리해두고, Java 코드에서 xml에 있는 SQL을 간단한 코드로 사용할 수 있게 되어있어서 쉽고 심플.

- 자바 코드에서 SQL문을 분리해서 관리

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

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

 

SQL과 Java코드가 한 소스 파일에 같이 섞여 있다. 

이걸 MyBatis를 이용하면 분리할 수 있다. 

<?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.UserMapper">
	<insert id="insert" parameterType="com.fastcampus.ch4.domain.UserData">
    	INSERT INTO user_info
        VALUES ( #{id}, #{pwd}, #{name}, #{email}, #{birth}, #{sns}, new());
    </insert>

이런식으로 xml에 sql만 따로  태그를 이용해서 따로 분리하고, 자바 코드는 다음과 같이 간단해진다. 

@Repository
public class UserDaoImpl implements UserDao { 
	@Autowired
    private SqlSession session;
    private static String namespace = "com.fastcampus.ch4.dao.UserMapper.";
    
    @Override
    public int insert(User user) {
    	return session.insert(namespace+"inserrt", user);
    }

 

 

 

<실습>

- ch4 파일을 다운받아서 인텔리제이에서 open. 

- 실습에 필요한 파일들 다운로드

- 인텔리제이 MySQL연결 후 테이블 생성

 

그리고 Maven Repository에서 다음 2개 코드를 복사한다. 

pom.xml

Spring에서 MyBatis를 사용하려면 이 2개의 모듈이 필요하다. 

 

 

2. SqlSessionFactoryBean과 SqlSession Template

- SqlSessionFactory : SqlSession을 생성해서 제공

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

=> 이 둘은 mybatis 모듈이 제공한다. 둘 다 인터페이스이다. 

 

이 인터페이스를 구현한게 아래와 같다.

- SqlSessionFactoryBean : SqlSessionFactory를 Spring에서 사용하기 위한 빈

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

=> 이 둘은 mybatis spring이 제공한다. 아래와 같이 빈으로 등록할 수 있다. (root-context.xml에 저장)

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

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

FactoryBean을 등록할 때 Mapper의 위치를 지정해줘야 한다. 
Mapper.xml은 SQL문이 들어있는 xml문서이다. 이걸 종류별로 여러개를 만들기 때문에 앞에 *패턴이 붙어있다. 

SqlSessionTemplate를 이용해서 Dao를 작성한다. 이 Dao가 여러 개 있을 수 있는데, SqlSessionTemplate을 
공유할 수 있다. 그 이유는 멀티 쓰레드에 안전한 thread-safe이기 때문이다.

여러 쓰레드가 동시에 접근해도 SqlSessionTemplate이 알아서 관리해주기 때문에 안전한 것은 큰 장점이다. 

 

 

 

3. SqlSession의 주요 메서드

메서드 설명
int insert(String statement)
int insert(String statement, Object parameter)
insert문을 실행하고, insert된 행의
갯수를 반환
int delete(String statement)
int delete(String statement, Object parameter)
delete문을 실행하고, delete된 행의
갯수를 반환
int update(String statement)
int update(String statement, Object parameter)
update문을 실행하고, update된 행의
갯수를 반환
T selectOne(String statement) 
T selectOne(String statement, Object parameter)
하나의 행을 반환하는 select에 사용
parameter로 SQL에 binding될 값 제공
List<E> selectList(String statement)
List<E> selectList(String statement, Object parameter)
여러 행을 반환하는 select에 사용
parameter로 SQL에 binding될 값 제공
Map<K,V> selectMap(String statement, String keyCol)
Map<K,V> selectMap(String statement, String keyCol, Object parameter)
여러 행을 반환하는 select에 사용
keyCol에 Map의 key로 사용할 컬럼

- int : ~ DB에 영향을 준 row의 수

-  selectOne : 한 행(row)

- selectList , selectMap : 여러개 행 (selectList를 더 많이 사용)

- Object parameter : insert into user_info value(?,?,?) -> 이 값들을 객체에 담아서 전달, User나 Map도 가능

- String statement : sql문 들어있는 xml의 이름 지정

 

 

4. Mapper XML의 작성

 

[boardMapper.xml]

<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>

SQL문을 하나씩 만들어두고, 

public class BoardDaoImpl implements BoardDao {
    @Autowired
    private SqlSession session;
    private static String namespace = "com.fastcampus.ch4.dao.BoardMapper.";

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

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

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

호출할 때 이름을 준다. 

 

 

 

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

 

mybatis – MyBatis 3 | Configuration

Configuration The MyBatis configuration contains settings and properties that have a dramatic effect on how MyBatis behaves. The high level structure of the document is as follows: configuration properties These are externalizable, substitutable properties

mybatis.org

<mapper namespace="com.fastcampus.ch4.dao.BoardMapper">
	<select id="now" resultType="string">
    	SELECT now()
    </select>
    
	<select id="count" resultType="int">
    	SELECT count(*) FROM board
    </select>
    
    <insert id ="insert" parameterType="com.fastcampus.ch4.domain.BoardDto">
    	INSERT INTO board
        	(title, content, writer)
        VALUES
        	(#{title}, #{content}, #{writer})
    </insert>
    
    <select id ="select" parameterType="int" 
						 resultType="com.fastcampus.ch4.domain.BoardDto">
 		SELECT bno, title, content, writer, view_cnt, comment_cnt, reg_date
		FROM board
        WHERE bno = #{bno}
    </select>

너무 긴 부분을 별명을 통해 짧게 하고자 한다면 다음과 같이 하면 된다. 

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

BoardDto가 별명, com.fast~가 실제 이름이다. 

별명은 대소문자를 구별하지 않고, 실제 이름은 대소문자를 구별한다. 

    <insert id ="insert" parameterType="BoardDto">
    	INSERT INTO board
        	(title, content, writer)
        VALUES
        	(#{title}, #{content}, #{writer})
    </insert>
    
    <select id ="select" parameterType="int" 
						 resultType="BoardDto">
 		SELECT bno, title, content, writer, view_cnt, comment_cnt, reg_date
		FROM board
        WHERE bno = #{bno}
    </select>