티스토리 뷰

개요

JAVA에 DB 프로그래밍을 하기 위해서 JDBC 제공되었다. JDBC RDB 사용을 위한 다양한 API 제공하지만, DB 방대해지고 data 관계가 복잡해짐에 따라 다수의 메소드를 호출하고 관련 객체를 해제해야 하는 문제점이 심화되었다. 이러한 문제점을 해결하고 더욱 효과적으로 DB 관리하기 위해 MyBatis 고안되었다.

MyBatis 개발자가 지정한 SQL, 저장 프로시저 그리고 고급 매핑을 지원하여 개발 생산성을 높이는 persistence framework이다. 기존 JDBC만을 이용한 방식은 프로그램 소스안에서 직접 connection 맺고 SQL문을 처리하고 rs.next() 등을 이용하여 하나씩 받아와야 해서 코드가 길어지고 SQL 변경이 필요한 경우에도 java 프로그램을 수정하기 때문에 유연성이 좋지 못했다. 그러나 MyBatis에서는 상당부분의 코드와 파라미터 설정 ResultSet 결과를 대신해주어 코딩의 중복과 무의미한 코드 작성을 생략할 있으면서도, SQL문을 xml 파일에 작성하여 변환이 자유롭고 가독성이 좋다.

Mybatis RDB 더욱 편하게 이용할 있도록 개발된 persistence framework이다.

 

 

동향

우리에게 엄청나게 익숙한 MyBatis이다. 대한민국은 MyBatis 공화국이니 말이다. 하지만...

 

MyBatis vs Hibernate

다른걸 설명하기 전에 이 충격적인 사실을 모르는 사람들을 위해 비슷한 성격을 가진 MyBatis와 Hibernate를 비교를 해봤다. 좌측은 국내에서 MyBatis와 Hibernate의 관심도이고 우측은 해외에서의 MyBatis와 Hibernate의 관심도이다. 그렇다.. 우리나라에 있으면 전세계가 모두 MyBatis를 사용하는것 같은데 실상은 우리와 중국, 일본만 MyBatis를 사랑한다. 그래도 우리나라에서는 엄청나게 많이 사용되고 있으니 잘 익혀두자. (우물안 개구리가 되지 않기 위해서는 Hibernate도 학습을 하자!)

 

특징

MyBatis 다음과 같은 특징을 갖는다.

  • 간단함 : 간단한 persistence framework. 배우기가 쉽다. 
  • 생산성 : 62%정도 줄어드는 코드, 간단한 설정
  • 성능 : 데이터 접근 속도를 높여주는 Join 매핑사용, 여러 방식의 데이터 가져오기 전략 (가져오기 미루기, SQL 줄이기 기법)
  • 작업의 분배
  • SQL문이 application source code 로부터 완전 분리
  • 이식성 : 어떤 프로그램이 언어로도 구현 가능 ex) java, C#, .NET …
  • 오픈소스

 

사용 방식


MyBatis
이용할 SQL문을 사용하는 방식은 크게 3가지로 나뉠 있다.

  1. XML만을 이용한 SQL문을 설정, DAO에서는 XML 찾아서 실행하는 코드로 작성
    • 장점 : SQL문은 별도로 XML 작성되어 SQL문의 수정이나 유지보수에 적합
    • 단점 : 개발 코드 양이 많아지고, 복잡성이 증가
  2. annotation 인터페이스만을 이용하여 SQL 설정
    • 장점 : 별도의 DAO 없이도 개발가능하여 생산성이 크게 증가
    • 단점 : SQL문을 annotation으로 작성하므로, 매번 수정이 일어나는 경우 다시 컴파일 필요
  3. 인터페이스와 XML 작성된 SQL문의 활용
    • 장점 : 간단한 SQL문은 annotation으로 복잡한 SQL문은 XML 처리하여 유연성이 좋음
    • 단점 : 개발자에 따라 개발 방식 차이로 인해 유지보수가 중요한 프로젝트에서는 부적합

설정 및 사용법

종속성(Dependency) 추가

스프링에서 MyBatis 사용하기 위해서는 라이브러리가 필요하다. Maven 이용할 경우 pom.xml 다음을 추가한다.

<properties>
    <mybatis.version>3.5.0</mybatis.version>
    <mybatis.spring.version>1.3.2</mybatis.spring.version>
    ...
</properties>

<dependencies>
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>${mybatis.version}</version>
  </dependency>
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>${mybatis.spring.version}</version>
  </dependency>
...

버전은 프로젝트에 알맞게 기입하도록 한다.

 

ApplicationContext 설정

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">
    
    <!-- sqlSessionTemplate -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory" />
    </bean>
 
    <!-- sqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:/mybatis/mybatis-config.xml" />
        <property name="mapperLocations">
	        <list> <!-- 여러 sql문을 받아오기 위해 list로 받아온다 -->
	            <value>classpath:sql/*.sql</value>
	        </list>
        </property>
    </bean>
 
    <!-- datasource spring profile 별로 설정 --> 
    <beans profile="local">   
        <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
            <!-- oracle 경우 -->
            <property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
            <property name="url" value="jdbc:oracle:thin:@IP주소:포트:스키마" />
            <property name="username" value="설정아이디" />
            <property name="password" value="설정패스워드">
        </bean>
    </beans>
</beans>

ApplicationContext에 MyBatis를 사용하기 위한 SqlSessionFactory와 datasource를 설정한다. SqlSessionTemplate과 SqlSessionFactory는 Mybatis의 핵심으로 MyBatis의 설정파일인 mybatis-config.xml과 Query 파일들의 위치를 설정한다. 그리고 이 Factory를 사용할 수 있도록 Template를 만들어둔다. 

 

mybatis-config.xml 설정

<?xml version="1.0" encoding="UTF-8"?><!--Converted at: Mon Feb 03 17:37:44	KST 2014 -->
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD SQL Map Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="cacheEnabled" value="true" />
        <setting name="lazyLoadingEnabled" value="true" />
        <setting name="multipleResultSetsEnabled" value="false" />
        <setting name="defaultExecutorType" value="SIMPLE" />
        <setting name="jdbcTypeForNull" value="VARCHAR"/>
        <setting name="callSettersOnNulls" value="true"/>
    </settings>
    <typeAliases>
        <typeAlias alias="HMap" type="java.util.HashMap" />
    </typeAliases>
    <plugins>
        <plugin interceptor="test.common.interceptor.LogInterceptor"/>
    </plugins>
</configuration>

MyBatis의 기본적인 설정을 할 수 있다. 세팅 가능한 내용은 아래의 별첨을 참조하자. 

SQL 구현  mapper 사용

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="commonCode">
    <select id="getCommonCodeList" resultType="HMap">
	SELECT	  CODE_NAME
      		, TO_CHAR(UPD_DTM, 'YYYY-MM-DD') AS UPD_DTM
	FROM      COMMON_CODE
    </select>
</mapper>

위의 ApplicationContext에 정의했던 mapperLocations에 해당하는 위치에 sql 파일을 생성한다. 그리고 그 안에 namespace id, statement id 를 정의하고 Query를 작성한다.  namespace id + statement id = query id 이고 이 값은 유일해야한다. 즉 위와 같은 경우는 query id는 commonCode.getCommonCodeList 이다. 

 

DAO 작성

@Repository
public class SampleDAO {

    @Autowired
    private SqlSessionTemplate sqlSession
 
    /*insert, delete, update, select 메소드 모두 재정의*/
    public Object select(String queryId, Object params){
        return sqlSession.select(queryId, params);
    }

    public List selectList(String queryId, Object params){
        return sqlSession.selectList(queryId,params);
    }
}

공통으로 사용하는 CommonDao를 사용하는 경우도 많지만 정의가 되어 있지 않다면 위와 같이 각 Service마다 그에 맞는 DAO를 작성해줘야한다. 여기에서의 queryId는 위에서 언급한 query id를 말하는것이다. 보통은 query id와 parameter 값을 넘겨주고 이를 통해 결과값을 받아서 리턴을 해준다. 

 

 


별첨

mybatis-config.xml settings 설정

런타임시 마이바티스의 행위를 조정하기 위한 중요한 값들이다.

설정 설명 사용가능한 값들 디폴트
cacheEnabled 설정에서 각 매퍼에 설정된 캐시를 전역적으로 사용할지 말지에 대한 여부 true | false true
lazyLoadingEnabled 지연로딩을 사용할지에 대한 여부. 사용하지 않는다면 모두 즉시 로딩할 것이다. 이 값은 fetchType 속성을 사용해서 대체할 수 있다. true | false false
aggressiveLazyLoading 활성화되면 모든 메서드 호출은 객체의 모든 lazy properties 을 로드한다. 그렇지 않으면 각 property 가 필요에 따라 로드된다. (lazyLoadTriggerMethods 참조). true | false false (3.4.1 부터 true)
multipleResultSetsEnabled 한개의 구문에서 여러개의 ResultSet을 허용할지의 여부(드라이버가 해당 기능을 지원해야 함) true | false true
useColumnLabel 칼럼명 대신에 칼럼라벨을 사용. 드라이버마다 조금 다르게 작동한다. 문서와 간단한 테스트를 통해 실제 기대하는 것처럼 작동하는지 확인해야 한다. true | false true
useGeneratedKeys 생성키에 대한 JDBC 지원을 허용. 지원하는 드라이버가 필요하다. true로 설정하면 생성키를 강제로 생성한다. 일부 드라이버(예를들면, Derby)에서는 이 설정을 무시한다. true | false False
autoMappingBehavior 마이바티스가 칼럼을 필드/프로퍼티에 자동으로 매핑할지와 방법에 대해 명시. PARTIAL은 간단한 자동매핑만 할뿐 내포된 결과에 대해서는 처리하지 않는다. FULL은 처리가능한 모든 자동매핑을 처리한다. NONE, PARTIAL, FULL PARTIAL
autoMappingUnknownColumnBehavior 자동매핑 대상중 알수 없는 칼럼(이나 알수없는 프로퍼티 타입)을 발견했을때 행위를 명시
  • NONE: 아무것도 하지 않음
  • WARNING: 경고 로그를 출력('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'의 로그레벨은 WARN이어야 한다.)
  • FAILING: 매핑이 실패한다. (SqlSessionException예외를 던진다.)
NONE, WARNING, FAILING NONE
defaultExecutorType 디폴트 실행자(executor) 설정. SIMPLE 실행자는 특별히 하는 것이 없다. REUSE 실행자는 PreparedStatement를 재사용한다. BATCH 실행자는 구문을 재사용하고 수정을 배치처리한다. SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout 데이터베이스로의 응답을 얼마나 오래 기다릴지를 판단하는 타임아웃을 설정 양수 설정되지 않음(null)
defaultFetchSize 조회결과를 가져올때 가져올 데이터 크기를 제어하는 용도로 드라이버에 힌트를 설정 이 파라미터값은 쿼리 설정으로 변경할 수 있다. 양수 설정하지 않음(null)
defaultFetchSize 결과를 가져오는 크기를 제어하는 힌트처럼 드라이버에 설정한다. 이 파라미터는 쿼리설정으로 변경할 수 있다. 양수 셋팅되지 않음(null)
defaultResultSetType Specifies a scroll strategy when omit it per statement settings. (Since: 3.5.2) FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(same behavior with 'Not Set') Not Set (null)
safeRowBoundsEnabled 중첩구문내 RowBound사용을 허용 허용한다면 false로 설정 true | false False
safeResultHandlerEnabled 중첩구문내 ResultHandler사용을 허용 허용한다면 false로 설정 true | false True
mapUnderscoreToCamelCase 전통적인 데이터베이스 칼럼명 형태인 A_COLUMN을 CamelCase형태의 자바 프로퍼티명 형태인 aColumn으로 자동으로 매핑하도록 함 true | false False
localCacheScope 마이바티스는 순환참조를 막거나 반복된 쿼리의 속도를 높히기 위해 로컬캐시를 사용한다. 디폴트 설정인 SESSION을 사용해서 동일 세션의 모든 쿼리를 캐시한다. localCacheScope=STATEMENT 로 설정하면 로컬 세션은 구문 실행할때만 사용하고 같은 SqlSession에서 두개의 다른 호출사이에는 데이터를 공유하지 않는다. SESSION | STATEMENT SESSION
jdbcTypeForNull JDBC타입을 파라미터에 제공하지 않을때 null값을 처리한 JDBC타입을 명시한다. 일부 드라이버는 칼럼의 JDBC타입을 정의하도록 요구하지만 대부분은 NULL, VARCHAR 나 OTHER 처럼 일반적인 값을 사용해서 동작한다. JdbcType 이늄. 대부분은 NULL, VARCHAR 나 OTHER 를 공통적으로 사용한다. OTHER
lazyLoadTriggerMethods 지연로딩을 야기하는 객체의 메소드를 명시 메소드 이름을 나열하고 여러개일 경우 콤마(,) 로 구분 equals,clone,hashCode,toString
defaultScriptingLanguage 동적으로 SQL을 만들기 위해 기본적으로 사용하는 언어를 명시 타입별칭이나 패키지 경로를 포함한 클래스명 org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
defaultEnumTypeHandler Enum에 기본적으로 사용되는 TypeHandler 를 지정합니다. (3.4.5 부터) 타입별칭이나 패키지 경로를 포함한 클래스명 org.apache.ibatis.type.EnumTypeHandler
callSettersOnNulls 가져온 값이 null일때 setter나 맵의 put 메소드를 호출할지를 명시 Map.keySet() 이나 null값을 초기화할때 유용하다. int, boolean 등과 같은 원시타입은 null을 설정할 수 없다는 점은 알아두면 좋다. true | false false
returnInstanceForEmptyRow MyBatis 는 기본적으로 모든 열들의 행이 NULL 이 반환되었을 때 null을 반환한다. 이 설정을 사용하면 MyBatis가 대신 empty 인스턴스를 반환한다. nested results(collection 또는 association) 에도 적용된다. 3.4.2 부터 true | false false
logPrefix 마이바티스가 로거(logger) 이름에 추가할 접두사 문자열을 명시 문자열 설정하지 않음
logImpl 마이바티스가 사용할 로깅 구현체를 명시 이 설정을 사용하지 않으면 마이바티스가 사용할 로깅 구현체를 자동으로 찾는다. SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 설정하지 않음
proxyFactory 마이바티스가 지연로딩을 처리할 객체를 생성할 때 사용할 프록시 툴을 명시 CGLIB | JAVASSIST JAVASSIST (마이바티스 3.3과 이상의 버전)
vfsImpl VFS 구현체를 명시 콤마를 사용해서 VFS구현체의 패키지를 포함한 전체 클래스명  
useActualParamName 메소드 시그니처에 명시된 실제 이름으로 구문파라미터를 참조하는 것을 허용 이 기능을 사용하려면 프로젝트를 자바 8의 -parameters옵션을 사용해서 컴파일해야만 한다.(마이바티스 3.4.1이상의 버전) true | false true
configurationFactory Configuration 인스턴스를 제공하는 클래스를 지정한다. 반환된 Configuration 인스턴스는 역직렬화 된 객체의 지연로딩 속성들을 불러오는데 사용된다. 이 클래스는 static Configuration getConfiguration() 메서드를 가져야 한다. (3.2.3 부터) 타입별칭이나 패키지 경로를 포함한 클래스명 설정하지 않음
shrinkWhitespacesInSql SQL에서 여분의 whitespace 문자들을 삭제한다. 이는 SQL의 리터럴 문자열에도 영향을 미친다. (Since 3.5.5) true | false false
defaultSqlProviderType Specifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the type(or value) attribute on sql provider annotation(e.g. @SelectProvider), when these attribute was omitted. A type alias or fully qualified class name Not set

 

끝!

댓글
최근에 올라온 글
최근에 달린 댓글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31