공부/MyBatis

MyBatis 란?

샤샤샤샤 2023. 10. 23. 10:53

기존에 SpringDataJPA만 사용해오다 이번 기회에 MyBatis를 사용할수 있게 되었다.

마이바티스 역시 근본적으로는 JPA와 마찬가지로 프로세스에서 DB에 더 쉽게 접근하기 위한 기술이다. 이 역시 JPA와 마찬가지로 JDBC를 근간으로 한다.

세계적으로는 우리나라와 중국, 일본 정도에서만 주류로 사용되며, 그 외의 국가들은 대부분 JPA(Hibernate) 가 대세이다. 그 이유는 간단한 쿼리문 작성에 JPA가 훨씬 강력한 성능을 뽐내기 때문인데, 반대로 복잡한 쿼리문에서는 MyBatis가 더 강하다.

또한 Persistence Framework 를 통해 데이터베이스와 연동 기술을 개발하는데, MyBatis 는 SQL Mapper 방식, JPA는 ORM(Object Relational Mapping)방식이다.

 

** SQL Mapper : Object 와 SQL 쿼리문의 결과를 매핑하여 데이터를 객체화하는 기술.

     객체와 테이블을 연결하는 것이 아닌, sql문을 통해 얻은 데이터를 어떤 객체에 매핑할지 사용자가 직접 바인딩하는 방법. 따라서 sql에 의존적이다.

*** ORM : Object와 DB테이블을 매핑하여 데이터를 객체화하는 기술.

    가벼운 CRUD관련 메소드가 이미 내장되어 있어 직접 SQL을 작성하지 않아도 됨으로 DBMS에 종속적이지 않다.

  MyBatis JPA
매핑  SQL Mapper
DBMS에 종속적이다.
ORM
DBMS에 자유롭다.
장점  sql이 비지니스 로직과 분리되어 있어 유지, 보수에 유리하다.
기존의 sql문법을 그대로 사용할수 있다.
개발자가 직접 sql문을 작성하지 않아도 된다.
sql문이 아닌 클래스의 케서드를 통해 db를 조작할수 있다.
DBMS에 종속적이지 않다.
단점 DBMS별로 sql문법이 다 다르다.
개발자가 직접 sql문을 작성해야 한다.
객체와 테이블간 패러다임 불일치가 발생한다.
sql을 직접 작성하는 것보다 성능이 
떨어질수 있다.
사용하기 위해서는 ORM 기술을 별도로 공부해야 한다.
n+1 문제 등이 발생할수 있다.

 

스프링에서 마이바티스 사용법

사전에 모든 디펜던시를 가져왔다는 가정 하에 설명한다.

 

1. resources 폴더 안에 실행될 쿼리문을 담을 mapper.xml 파일을 만든다.

 필자는 resource 폴더 내부에 mapper 라는 폴더를 하나 더 만들었다.

 

2. 실행될 쿼리문을 작성한다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.com.com.mapper.BoardMapper">   -- 1

    <select id="findAll" resultType="BoardVO">   ---2
        select * from board_study
    </select>
    <!-- 모든 데이터를 가져오는 쿼리문 -->
</mapper>

1번 코드가 상당히 중요한데, 이는 쿼리문과 연동될 함수가 정의되어 있는 interface 파일의 경로다. 이후 해당 interface 의 함수가 호출될때 퀴리문이 실행된다.

 

2번의 id는 쿼리문을 실행할 interface 함수 이름과 동일하게 맞춰줘야 한다.

resultType 는 어떤 타입의 객체에 쿼리문 결과를 바인딩할지 지정해주는데, 기본적으로 hashmap 이나 String이 가능하며, 그외에 사용자가 직접 만든 객체에 바인딩하고 싶으면 별도의 설정이 필요하다.

 

 

 

3. mapper.xml 설정 파일을 만들어준다( 선택사항 ).

log4j.xml은 db에 접근시 로그에 대한 설정 파일이다.

<?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>
	<settings>
		<setting name="jdbcTypeForNull" value="NULL" />    --1
	</settings>
	<typeAliases>
		<typeAlias type="com.com.com.vo.BoardVO" alias="BoardVO"/>      --2
		<typeAlias type="com.com.com.dto.BoardDTO" alias="BoardDTO"/>
	</typeAliases>
    
	<mappers>
		<mapper resource="mapper/mapper.xml" />    --3
	</mappers>
    
</configuration>

1번 코드는 쿼리에 들어올 파라미터에 null 값이 있을 경우 에러를 방지하기 위한 세팅이다.

2번 코드는 데이터가 담길 객체 클래스를 직접 바인딩해주는 코드로, resultType 뿐만 아니라 parameterType역시 사용자가 만든 객체를 사용하고자 하면 이를 설정해줘야 한다.

3번 코드는 mapper.xml 파일과 현재 설정 파일을 연동시키는 코드다. 이 경로가 잘못되거나 문제가 생기면 설정이 적용되지 않는다.

 

4. mapper 인터페이스 생성

package com.com.com.mapper;

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

import com.com.com.dto.BoardDTO;
import com.com.com.vo.BoardVO;

public interface BoardMapper {
	List<BoardVO> findAll();  
}

해당 인터페이스는 쿼리문과 연동될 함수를 정의하는 공간이다. 2번 과정에서 xml 파일을 작성할때 id값으로 준 값과 함수 이름이 동일하면, 함수가 호출될때 쿼리문이 실행된다.

 

5. DAO 파일 생성

DAO란 DataAccessObject의 약자로 기본적인 crud작업을 담당하는 객체다.

이곳에서 앞서 만든 mapper 인터페이스를 상속받아 구체화 시킬수 있다.

@Repository 가 붙는 객체로, db에 접근하는 메서드를 사용하기 위한 인터페이스다.

 

package com.com.com.dao;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.com.com.mapper.BoardMapper;
import com.com.com.vo.BoardVO;

@Repository
public class BoardDAO implements DAOInter {
	
	@Autowired
	private SqlSession sqlSession;
	
	public List<BoardVO> findAll(){
		BoardMapper mapper = sqlSession.getMapper(BoardMapper.class);
		List<BoardVO> boardList = mapper.findAll();
		return boardList;
	}
	
}

 

이로서 모든 구현이 끝났다. 이제 BoardDAO 의 findAll 함수를 호출하면 앞서 정의한 쿼리문이 실행된다.

 

그런데 코드를 보면 SqlSession 이라는 클래스가 갑자기 등장해 의존주입을 받고 있다.

이는 사전 설정 단계에서 미리 빈으로 등록해둔 것인데, 이는 MyBatis를 이용한 sql문 실행 및 트랜잭션 제어를 위한 API를 제공하는 가장 중요한 구성요소이다.

또한 SqlSession 을 사용하기 위해선 SqlSession 을 생성하는 SqlSessionFactory 의 빈 등록 역시 사용자가 직접 해줘야한다.

 

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

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

 

MyBatis 의 동작 방식

1~3은 프로세스 시작시 수행되는 과정이다.

(1)에서 SqlSessionFactory를 빌드 요청을 받고, (2)에서 SqlSessionFactory를 빌드하기 위한 설정 파일을 읽어 (3)에서 SqlSessionFactory의 빌드가 끝난다. 

그러나 4~10의 과정은 클라이언트의 요청이 들어올때 동작하는 과정이다.

(4)에서 클라이언트가 어떤 프로세스를 요청하면, (5) 프로그램은 SqlSessionFactory에서 SqlSession을 가져와 (6) SqlSession 객체를 생성하고 이를 어플리케이션에 반환한다. 이후 SqlSession은 (7)번에서 Mapper 인터페이스 구현 개체를 가져오고, (8) 에서 매퍼의 인터페이스 메소드를 실행, 그에 대응하여 알맞은 sql 문이 실행되는 것이 (9), (10) 과정이다.