본문 바로가기
Mybatis

Mybatis 간단 정리

by teg0 2025. 10. 20.

Mybatis

sql을 단순히 문자열로 작성하는 대신, XML 내부에서 if, choose, where 등의 테어 태그를 이용해, 조건에 따라 sql 문장을 동적으로 생성할 수 있다. (EL 구문과 비슷하다.)

마이바티스를 사용하는 가장 큰 이유는 동적 SQL을 사용할 수 있기 때문이다.

정적인 SQL은 같은 기능이지만, 들어오는 값에 따라 같은 기능을 하는 SQL문을 만들어줘야 한다.

즉, 가독성, 재사용성 등이 떨어진다. 

그렇기에 마이바티스는 동적 SQL을 지원하여 같은 기능을 하는 SQL문에 if, choose, where 등을 사용하여 값에 따라 동적으로 실행할 수 있다.

 

mybatis 실행을 위한 설정 파일

mybatis-config.xml라는 파일을 사용하여 원래 사용하던 Oralce-Driver와 SQL문을 저장한 경로를 정해주면, 마이바티스 프레임워크가 자동으로 경로를 따라가 SQL문을 실행해 준다.

<configuration>

	<!-- 자주 사용하는 VO클래스들의 풀 클래스명을 단순한 별칭으로 사용하기 위한 별칭 등록 -->
	<typeAliases>
		<typeAlias type="com.kh.mybatis.model.vo.Member" alias="Member"/>
		<typeAlias type="com.kh.mybatis.model.vo.Board" alias="Board"/>
		<typeAlias type="com.kh.mybatis.model.vo.Attachment" alias="Attachment"/>
		<typeAlias type="com.kh.mybatis.model.vo.Category" alias="Category"/>
		<typeAlias type="com.kh.mybatis.model.vo.Reply" alias="Reply"/>
	</typeAliases>
	
	<!-- environments : mybatis실행시 연결할 디비정보 -->
	<environments default="development">
	  <environment id="development">
	  	<!-- transactionManager : JDBC(수동커밋) | MANAGED(자동커밋) 중 선택  -->
	    <transactionManager type="JDBC"/>
	    <!-- dataSource : 데이터베이스 정보를 기입-->
	    <!--       type : POOLED(커넥션풀 사용) | UNPOOLED(커넥션풀 사용안함) 
	    	  connectionPool : Connection객체를 담아둘 수 있는 영역
	    	  				   한번 생성된 Connection객체를 담아두고 재사용 해준다.
	    -->
	    <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="C##JSP"/>
	      <property name="password" value="JSP"/>
	    </dataSource>
	  </environment>
	</environments>
	
	<mappers>
	  <mapper resource="/mappers/member-mapper.xml"/>
	  <mapper resource="/mappers/board-mapper.xml"/>
	</mappers>

</configuration>

첫 번째 typeAliases는 자주 사용하는 풀 클래스 이름을 별명을 붙여 간단하게 사용할 수 있도록 지정해 주는 태그이다.

풀 클래스 이름은 SQL문 파일에 사용된다.

 

두 번째 environments는 오라클 드라이버를 지정해 주는 태그이다.

environments = DB연결 정보
transactionManager = JDBC → 수동 커밋 방식
dataSource = POOLED → 커넥션 풀 사용
typeAliases로 VO에 별칭 부여
mappers 태그로 매퍼 XML 파일 경로 등록

 

세 번째 mapper는 SQL문을 사용하기 위한 경로를 지정해 준다.

 

SQL mapper 파일

<resultMap id="boardResultMap" type="Board">
    <result column="BOARD_NO" property="boardNo"/>
    <result column="BOARD_TYPE" property="boardType"/>
    <result column="CATEGORY_NO" property="categoryNo"/>
    <result column="CATEGORY_NAME" property="categoryName"/>
    <result column="BOARD_TITLE" property="boardTitle"/>
    <result column="BOARD_CONTENT" property="boardContent"/>
    <result column="BOARD_WRITER" property="boardWriter"/>
    <result column="MEMBER_ID" property="memberId"/>
    <result column="COUNT" property="count"/>
    <result column="CREATE_DATE" property="createDate"/>
</resultMap>

vo 객체에 저장된 필드명과 DB에 저장된 테이블의 칼럼명을 수동으로 맞추기 위해 작성한다.

결과 값의 타입을 변환해 준다.

resultMap은 여러 개 작성할 수 있기 때문에 많은 객체를 작성할 수 있다.

 

<select id="selectAttachment" parameterType="_int" resultMap="attachmentResultMap">
    SELECT FILE_NO,
            ORIGIN_NAME,
            CHANGE_NAME,
            FILE_PATH,
            FILE_LEVEL
      FROM ATTACHMENT
     WHERE REF_BNO = #{refBoardNo}
</select>

태그는 select, create, delete, update 등 sql에서 사용할 수 있는 CRUD를 태그로 사용한다. 

id는 자바에서 사용할 고유 이름, parameterType은 SQL에 들어갈 변수 타입, resultMap은 결괏값의 타입이다.

마찬가지로 SQL문을 여러 개 작성할 수 있다.

 

<select id="searchAllBoard" resultMap="boardResultMap">
    SELECT  BOARD_NO, 
            CATEGORY_NAME,
            BOARD_TITLE,
            MEMBER_ID,
            COUNT,
            TO_CHAR(CREATE_DATE, 'YYYY-MM-DD') AS "CREATE_DATE"
    FROM BOARD B
    JOIN CATEGORY USING(CATEGORY_NO)
    JOIN MEMBER M ON(BOARD_WRITER = MEMBER_NO)
    WHERE B.STATUS = 'Y'
    AND BOARD_TYPE = 1
    <choose>
        <when test="condition == 'writer'">
            AND MEMBER_ID
        </when>
        <when test="condition == 'title'">
            AND BOARD_TITLE
        </when>
        <otherwise>
            AND BOARD_CONTENT
        </otherwise>
     </choose>
      LIKE '%${keyword}%'
    ORDER BY BOARD_NO DESC
</select>

마이바티스에서 지원하는 동적 쿼리를 이용해 작성한 게시글 목록 조회이다.

결과 타입은 board 객체 타입이며, 다수 분기 choose를 받는 값에 따라 실행할 SQL문이 달라진다.

 

Service

public ArrayList<Board> selectAllBoard(PageInfo pi){
    SqlSession sqlSession = Template.getSqlSession();

    ArrayList<Board> list = boardDao.selectAllBoard(sqlSession, pi);

    sqlSession.close();

    return list;
}

자바에서 service 형태가 달라진다. 기존의 connection이나 rollback, commit 등 템플릿을 미리 작성하지 않아도 마이바티스가 지원해 준다. 

 

Dao

//기존 JDBC를 이용
public ArrayList<Board> selectAllBoard(Connection conn, PageInfo pi){
    //select -> ResultSet(여러개) -> ArrayList
    ArrayList<Board> list = new ArrayList<>();

    PreparedStatement pstmt = null;
    ResultSet rset = null;

    String sql = prop.getProperty("selectAllBoard");

    try {
        /*
         * currentPage : 1 -> 1~10    boardLimit : 10
         * currentPage : 2 -> 11~20
         * currentPage : 3 -> 21~30
         */
        int startRow = (pi.getCurrentPage() - 1) * pi.getBoardLimit() + 1;
        int endRow = startRow + pi.getBoardLimit() - 1;

        pstmt = conn.prepareStatement(sql);
        pstmt.setInt(1, startRow);
        pstmt.setInt(2, endRow);

        rset = pstmt.executeQuery();

        while(rset.next()) {
            Board b = new Board();
            b.setBoardNo(rset.getInt("BOARD_NO"));
            b.setCategoryName(rset.getString("CATEGORY_NAME"));
            b.setBoardTitle(rset.getString("BOARD_TITLE"));
            b.setMemberId(rset.getString("MEMBER_ID"));
            b.setCount(rset.getInt("COUNT"));
            b.setCreateDate(rset.getString("CREATE_DATE"));

            list.add(b);
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(rset);
        close(pstmt);
    }

    return list;
}

//마이바티스를 이용
public ArrayList<Board> selectAllBoard(SqlSession sqlSession, PageInfo pi){
    int offset = (pi.getCurrentPage() - 1) * pi.getBoardLimit();
    RowBounds rowBounds = new RowBounds(offset, pi.getBoardLimit());

    ArrayList<Board> list = (ArrayList)sqlSession.selectList("BoardMapper.selectAllBoard", null, rowBounds);

    return list;
}

Dao는 더 간단해진다. select를 사용하지위해 ResultSet, PreparedStatement을 이용하고 닫아주는 번거로운 작업을 하지만, 마이바티스는 SQL를 따로 빼낸 xml의 태그인 <mapper namespace="BoardMapper">의 BoardMapper에 연결 연산자 . 을 쓰고 SQL문의 id를 적는다. 그 뒤에는 SQL문에 전달할 변숫값을 넣어준다.

탑 n형식일 경우 3번째에 RowBound 설정한 후 넣어준다.