본문 바로가기
Spring 프레임워크/메모

[ Spring ] MyBatis 연결 하기 02

by Hwanii_ 2023. 10. 2.
728x90

이 게시글은 Spring 프로젝트 Maven )  에서 매퍼 인터페이스와 매퍼 XML 파일을 연결하는 방식을 정리 한다.
 
아래의 링크 에서는 Spring 프로젝트 에서 SQLSessionTemplate 템플릿 패턴을 활용 하여,
SQLSessionTemplate 을 사용하는 DAO 클래스와 매퍼 XML 파일을 연결하는 방식의 MyBatis 설정 방법 이였다.
 
https://hwanii96.tistory.com/425

 

[ Spring ] MyBatis 연결 하기 01

개요 지난 프로젝트 에서, 처음에는 JDBC 인터페이스의 preparedStatement 를 사용한 방식의 DAO 였고, 두번째는 JdbcTemplate 템플릿 패턴을 활용한 방식의 DAO 였다. SpringBoot 에서 MyBatis 프레임워크 적용 방

hwanii96.tistory.com


위와 같이 템플릿 패턴을 활용 하는 방법은,
루트 컨테이너에 반드시 SQLSession 빈과 SQLSessionTemplate 빈을 등록 하는 설정을 했었어야 하는데,
 
@Mapper 어노테이션을 사용하여 매퍼 인터페이스와 매퍼 XML 파일을 연결하는 방식으로 MyBatis 설정을 한다면,
더이상 루트 컨테이너에 SQLSessionTemplate 빈을 등록하는 설정이 필요 없게 된다.
 
또한,
그외의 필요한 설정은 Java 클래스를 사용하여 설정 해보려고 한다.
(매퍼 인터페이스 경로 설정, DataSource 빈 연결, 매퍼 XML 파일 경로 설정, ..)
 
 
 
1.
본인의 환경에맞는 MyBatis 버전으로 pom.xml 파일에 라이브러리를 추가 한다.
 

 
2.
본인이 설정한 루트 컨테이너 (applicationContext.xml) 에 DataSource 빈을 설정 한다.
 

 
3.
매퍼 XML 파일을 생성 하고 스키마 및 쿼리문 작성 하기.
 
본인은 src/main/resource 경로에 mybatis 패키지 하위에 사용할 매퍼 XML 파일을 생성 했다.
 

 

 
위의 이미지와 같이 스키마를 작성하고,
<mapper> 태그 내부에 namespace 속성의 값으로,
본인이 사용할 매퍼 인터페이스의 위치를 지정 한다.
MyBatis 버전이 3.x 이상일 경우, 패키지 경로를 포함한 인터페이스 이름을 명시 해주면 된다.
 
매퍼 인터페이스 이름과 매퍼 XML 파일은 동일하게 작성해준다.
 
매퍼 인터페이스 이름이 BoardMapper.java 이면, 매퍼 XML 파일의 이름도 BoardMapper.xml 로 생성 한다.
 

이런식으로

 
 
아직 인터페이스를 생성 하지 않았을테니, 생성 하고 설정 하면 된다.
 
매퍼 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="본인의 매퍼 인터페이스 위치">

    <insert id="insert">
        INSERT
        INTO BOARD (BNUM, MID, MNAME, PNUM, BCONTENT, BSTAR)
        VALUES ((SELECT NVL(MAX(BNUM), 0) + 1 FROM BOARD), (#{mID}, #{mName}, #{pNum}, #{bContent}, #{bStar}))
    </insert>

    <select id="selectAll" resultType="com.spring.biz.board.BoardVO">
        <choose>
            <when test="sk == 'PRODUCT'">
                SELECT ROW_NUMBER() OVER (ORDER BY BNUM)
                AS RNUM, B.BNUM, B.MID, B.PNUM, B.BCONTENT, B.BSTAR, B.BDATE, B.MNAME, P.PNAME
                FROM BOARD B INNER JOIN PRODUCT P ON B.PNUM = P.PNUM
                WHERE P.PNUM = #{pNum}
            </when>
            <when test="sk == 'MYPAGE'">
                SELECT ROW_NUMBER() OVER (ORDER BY BNUM)
                AS RNUM, B.BNUM, B.MID, B.PNUM, B.BCONTENT, B.BSTAR, B.BDATE, B.MNAME, P.PNAME, P.PIMAGE
                FROM BOARD B INNER JOIN PRODUCT P ON B.PNUM = P.PNUM
                WHERE MID = #{mID}
            </when>
        </choose>
    </select>

    <select id="selectOne" resultType="com.spring.biz.board.BoardVO">
        SELECT *
        FROM BOARD
        WHERE BNUM = #{bNum}
    </select>

    <update id="update">
        UPDATE BOARD
        SET BCONTENT = #{bContent},
            BSTAR    = #{bStar}
        WHERE BNUM = #{bNum}
    </update>

    <delete id="delete">
        DELETE
        FROM BOARD
        WHERE BNUM = #{bNum}
    </delete>

</mapper>

 
4.
매퍼 인터페이스를 생성 하고 작성 하기.
 
본인은 src/main/java/com/spring/mapper 경로 하위에 인터페이스를 생성 했다.
 

 
 

 
인터페이스에 @Mapper 어노테이션을 설정 한다.
 
@Mapper 어노테이션을 설정 하면, 해당 인터페이스가 서버가 시작할 때 메모리에 올라오게 된다.
 
매퍼 인터페이스 예시
 

더보기

 

package com.spring.mapper;

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

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import com.spring.biz.board.BoardVO;

@Mapper
public interface BoardMapper {

    boolean insert(Map<String, String> map);

    List<BoardVO> selectAll(Map<String, String> map);

    BoardVO selectOne(@Param("bNum") int bNum);

    boolean update(Map<String, String> map);

    boolean delete(@Param("bNum") int bNum);

}   //  BoardMapper

 

C, R, R, U, D 메서드를 작성 했고,

 

메서드의 인자로는 DTO (VO) 객체를 받지 않고,

map 컬렉션 객체,

@Param 어노테이션을 사용한 파라미터 값 으로 받는것으로 작성 했다.

 

설계 방식의 차이 이다.

 
5.
매퍼 인터페이스를 사용하는 주체인 서비스 레이어에 매퍼 인터페이스를 DI 한다.
 

 

 
서비스 레이어 예시
 

더보기

 

package com.spring.biz.board;

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

import com.spring.mapper.BoardMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("boardService")
public class BoardServiceImple implements BoardService {

    @Autowired
    private BoardMapper boardMapper;

    @Override
    public boolean insert(BoardVO boardVO) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("mID", boardVO.getmID());
        map.put("mName", boardVO.getmName());
        map.put("pNum", String.valueOf(boardVO.getpNum()));
        map.put("bContent", boardVO.getbContent());
        map.put("bStar", String.valueOf(boardVO.getbStar()));
        return boardMapper.insert(map);
    }

    @Override
    public List<BoardVO> selectAll(BoardVO boardVO) {

        Map<String, String> map = new HashMap<String, String>();
        map.put("sk", boardVO.getSk());
        map.put("pNum", String.valueOf(boardVO.getpNum()));
        map.put("mID", boardVO.getmID());
        return boardMapper.selectAll(map);
    }

    @Override
    public BoardVO selectOne(BoardVO boardVO) {
        return boardMapper.selectOne(boardVO.getbNum());
    }

    @Override
    public boolean update(BoardVO boardVO) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("bContent", boardVO.getbContent());
        map.put("bStar", String.valueOf(boardVO.getbStar()));
        map.put("bNum", String.valueOf(boardVO.getbNum()));
        return boardMapper.update(map);
    }

    @Override
    public boolean delete(BoardVO boardVO) {
        return boardMapper.delete(boardVO.getbNum());
    }

}    // BoardServiceImple

 
6.
매퍼 인터페이스와 매퍼 XML 파일을 매핑 하기 위해서, 자바 클래스를 생성 하기.
 
본인은 src/main/java/com/spring/biz/common 패키지 하위에 클래스를 생성 했다.
 

 
MyBatis 설정을 위한 자바 클래스 이름은 MyBatisConfig 라고 지어줬다.
 
아래와 같이 코드를 작성 한다.
 

 
AOP 에서 횡단관심 설정을 하기 위해서 @Aspect 어노테이션을 설정하듯이,
 
MyBatis 설정 파일임을 스프링에게 알려주기 위해서 @Configuration 어노테이션을 작성 한다.
 
@MapperScan 어노테이션은 본인이 작성한 매퍼 인터페이스가 있는 경로를 잡아 주면 된다.
(매퍼 인터페이스 스캔 설정은 루트 컨테이너에서 설정 할 수도 있음)
 
DataSource,
매퍼 XML 파일 경로 등을 설정 하기 위한 메서드를 작성 하고,
@Bean 어노테이션으로 해당 메서드를 메모리에 올려 주면 된다.
 
sqlSession 객체를 팩토리 패턴으로 객체화 하고,
sqlSession 참조변수를 사용해서
DataSource를 set 하고,
매퍼 XML 파일 경로도 set 한다.
 
반환되는 sqlSession.getObject() 값의 타입이 SqlSessionFactory 타입이여서,
반환 타입을 SqlSessionFactory로 작성 했다.
 
 
 
정리
 
1) pom.xml 파일에 MyBatis 관련 라이브러리 추가 하기.
 
2) applicationContext.xml (루트 컨테이너) 에 DataSource 빈 등록 및 설정 하기.
 
3) 매퍼 XML 파일을 생성 하고 스키마 및 쿼리문 작성 하기.
 
4) 매퍼 인터페이스를 생성 하고 @Mapper 어노테이션 설정 및 CRUD 메서드 작성 하기.
 
5) 매퍼 인터페이스를 사용하는 서비스 레이어에 매퍼 인터페이스를 DI 하기.
 
6) 매퍼 인터페이스와 매퍼 XML 파일을 매핑 하기 위한 자바 클래스 생성 및 설정 하기.
>>
@Configuration
@MapperScan
@Bean
 
위와 같이 설정 하면 maven 설정 파일을 사용하는 스프링 프로젝트와 마이배티스를 연결 할 수 있다.
 
만약 연결이 되지 않으면,
매퍼 인터페이스의 경로 지정이 잘못됬거나,
매퍼 XML 파일 경로 지정이 잘못됬거나 등의 이유일 가능성이 크다.
 
본인의 경우에는
매퍼 XML 파일에
namespace 속성 값으로 매퍼 인터페이스 경로를 제대로 설정해주지 않아서 아래의 예외가 발생했었다.
 

 

 
위와 같이 매퍼 인터페이스 이름만 명시해줬었는데,
에러가 발생 해서,
아래와 같이 경로 + 이름을 작성 해서 에러를 해결 했다.
 

반응형