KyungHwan's etc.

스프링프레임워크 -Mybatis 본문

Java/스프링프레임워크

스프링프레임워크 -Mybatis

KyungHwan_0 2018. 5. 31. 17:40

Mybatis


객체지향 언어인 자바의 관계형 데이터베이스 프로그래밍을 좀더 쉽게 개발 할수 있도록 도와 주는 개발 프레임워크 이다.

자바에선 데이터베이스 프로그래밍을 하기 위해 JDBC(자바에서 제공하는 데이터베이스프로그래밍 API)를 제공하며, 각 데이터베이스 소프트웨어 별로 jdbc드라이버를 통해서 자바와 데이터베이스를 연동시켜 접근하게 된다.

하지만, 다양한 관계형 데이터베이스를 지원하기 위해 JDBC는 세부적인 작업이 가능하게 각가의 메소드를 호출하게 되며, 이러한 사항들로 인해서 다수의 메소드를 호출하게 되고, 관련된 객체를 해제해야 하는 단점이 있다. 즉, 코드량이 불필요하게 많아지고, 유지보수 하기 어렵다는 측면이 있다.

MyBatis의 사용은 기존의 JDBC를 이용한 프로그래밍을 하는 방식에 비해서 개발자의 부담을 굉장히 덜어주고, 생산성과, 유지보수가 좋다는 측면이 있다.

MyBatis 의 특징

  • 간단하다 : 간단한 퍼시스턴스 프레임워크

  • 생산성 : 62%정도 줄어드는 코드 , 간단한 설정

  • 성능 : 구조적강점(데이터 접근 속도를 높여주는 Join 매핑) 여러가지 방식의 데이터를 가져오기 전략 (가져오기 미루기 , SQL 줄이기 기법)

  • 관심사의 분리 : 설계를 향상 (유지보수성) 소스를 관리하여 계층화를 지원(커넥션,PreparedStetement,결과셋)

  • 작업의 분배 : 팀을 세분화하는 것을 도움

  • SQL문이 애플리케이션 소스 코드로부터 완전 분리

  • 이식성 : 어떤 프로그래밍 언어로도 구현가능 (자바,C#,.NET,RUBY)

  • 오픈소스이며 무료이다.

MyBatis 와 DB연결 방식

Database Connetion Pool(DBCP)

JDBC를 통하여 DB에 연결할 경우, 매번 드라이버를 로드하고 Connection 객체를 가져와야하는데 매우 비효율적이다. 이를 해소하기 위해 웹 컨테이너가 실행되면서 DB와 연결된 Connection 객체를 미리 pool에 생성해두고 필요할 때에 가져다 쓰고 반환한다. DB의 부하를 줄이고 유동적으로 연결을 관리 할 수있다.

SessionFactory

단일 데이터 저장소, 안정적인 스레드를 위한 목적으로 사용된다. SessionFactory를 사용함으로서 다수의 스레드가 DB세션에 동시에 접근가능하며, 특정 데이터베이스에 매핑되 캐시가 변하지 않는다. SessionFactory는 프로그램이 실행될 때만 생성되고, 프로그램 내의 소스코드가 이에 접근할 수 있도록 Singleton형태를 지닌다.

SessionTemplate

MyBatis 에서는 SqlSessionTemplate라는 이름으로 쓰이고, Mybatis에서 있는 연동모듈의 핵심이다 SqlSessionTemplate은 SqlSession을 구현하고 코드에서 SqlSession를 대체하는역할을 하며 여러 개의 DAO나 매퍼에서 공유할수 있다. 또한 SqlSessionTemplate은 필요한 시점에 세션을 닫고, 커밋하거나 롤백하는 것을 포함한 세션의 생명주기를 관리하다.

MyBatis 사용하기

1. MyBatis 라이브러리 추가

스프링에서 MyBatis를 사용하려면 라이브러리가 필요하다. 우리는 이미 Maven을 이용하여 라이브러리를 관리하기 때문에, 라이브러리의 추가가 굉장히 쉽다. pom.xml에 다음을 추가한다.

Pom.xml

<dependency>
   <groupId>org.mybatis</groupId>
   <artifactId>mybatis</artifactId>
   <version>3.2.2</version>
</dependency>

<dependency>
   <groupId>org.mybatis</groupId>
   <artifactId>mybatis-spring</artifactId>
   <version>1.2.0</version>
</dependency>

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-jdbc</artifactId>
   <version>${org.springframework-version}</version>
</dependency>

<dependency>
   <groupId>commons-dbcp</groupId>
   <artifactId>commons-dbcp</artifactId>
   <version>1.4</version>
</dependency>

메이슨을 이용하여 MyBatis 라이브러리를 추가할수도 있다.

다음은 데이터베이스 별로 다른 설정방법이다.

1. MySql을 사용할 경우


<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.31</version>
</dependency>

2. Oracle**의 경우**


<repositories>
   <repository>
       <id>mvn2</id>
       <url>http://repo1.maven.org/maven2/</url>
       <releases>
           <enabled>true</enabled>
       </releases>
       <snapshots>
           <enabled>true</enabled>
       </snapshots>
   </repository>
   
   <repository>
        <id>oracle</id>
        <name>ORACLE JDBC Repository</name>
        <url>http://mesir.googlecode.com/svn/trunk/mavenrepo</url>
   </repository>
</repositories>

2016, 04, 26 부로 메이븐 추가 주소가 바뀌었다.


<repositories>
    <repository>
        <id>mesir-repo</id>
        <url>https://maven.atlassian.com/3rdparty/</url>
    </repository>
</repositories>    
<!-- https://mvnrepository.com/artifact/com.oracle/ojdbc6 -->
<dependency>
    <groupId>com.oracle</groupId>
    <artifactId>ojdbc6</artifactId>
    <version>12.1.0.1-atlassian-hosted</version>
</dependency>

3. MyBatis 와 DB(데이터베이스) 연결 설정

1) src/java/resource 폴더 밑에 config > spring 폴더를 만들다.

2) spring 폴더 안에 context-datasource.xml 파일을 만든다.

3)web.xml에서 위의 설정파일이 읽도록 설정 되어있는지 확인한다.

Web.xml의 하단에 다음의 코드가 있어야한다.

<context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:config/spring/context-.xml</param-value>
</context-param>

이는 최초 서버가 시작될 때, 해당 위치에 있는 context 파일을 모조리 읽어들이는 것을 뜻한다.
xml 태그에서 알 수 있듯이, contextConfigLocation을 설정하고, 그 위치는 위에서 만들었던 config > spring 폴더에 있는 context-로 시작하는 모든 xml 파일을 의미한다. 앞으로 스프링 관련 여러가지 설정파일이 있기 때문에, 위와같이 설정파일을 읽어올 수 있도록 하였다

4)MtBatis 연결 설정

MySql의 경우

<?xml version="1.0" encoding="UTF-8"?>
<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">
   
   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
       <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
       <property name="url" value="jdbc:mysql://주소/스키마"/>
       <property name="username" value="아이디"/>
       <property name="password" value="비밀번호"/>
   </bean>
</beans>

URL에서 MySQL이 설치된 서버의 주소와 사용할 DB스키마를 적어주면 된다.

(개인PC에서 개발할 경우 localhost/스키마 또는 127.0.0.1/스키마 로 적어주면 된다)

**Oracle의 경우**

<?xml version="1.0" encoding="UTF-8"?>
<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">
   
   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
       <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
       <property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
       <property name="username" value="아이디"/>
       <property name="password" value="비밀번호"/>
   </bean>
</beans>

MySQl과 다른점은 dataSource의 class와 url이 다르다.

4. MyBatis와 Spring의 연결

1) resource 폴더에 mapper 폴더 생성한다.

2) resource > config > spring 폴더에 context-mapper.xml 파일을 생성한다.

3) context-mapper.xml 파일에 다음의 내용을 작성한다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="<http://www.springframework.org/schema/beans>"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">



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

 
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
       <constructor-arg index="0" ref="sqlSession"/>
</bean>
</beans>

Porperty의 name과 ref과 dataSource로 정의되어있다.

이두가지는 같은 것을 의미하지 않는다. Name은 위에서 등록한 sqlSession 빈(been)에서 사용할 이름이 dataSource이고, ref의 dataSource는 우리가 context-datasource.xml에서 정의한 빈(been)을 참조하는 것을 의미한다.

mapperLocations는 앞으로 우리가 작성할 SQL문이 위치할 장소이다. 여기서 classpath:/mapper/*/_SQL.xml 이라는 정의를 살펴보자.

앞에서 web.xml에서 spring context 설정파일을 읽어오기 위해서 classpath:config/spring/context-.xml 라고 정의했던것을 기억하자.

앞으로 우리는 다양한 SQL 파일을 만들것인데, 그것을 일일이 등록해서 사용할 수는 없다. (원래는 xml 파일에 XML도 bean으로 설정해야한다.) 그렇지만 다양한 사람들이 작업하는 프로젝트의 특성상, 그것을 일일이 등록할 수 없고, 할 수 있더라도 귀찮은 일이다. 따라서 서버가 시작될 때 자동으로 SQL이 정의되어 있는 XML 파일도 읽어오도록 하는것이 필요하다.

따라서 SQL이 위치할 mapper 폴더를 잡아주고, 그 안에 모든 폴더를 의미하는 **를 붙여준 후, 마지막으로 _SQL로 끝나는 모든 xml 파일을 읽어주도록 한다.

여기서 중간에 ** 를 붙인 이유는, 유연한 폴더구조의 변경을 위해서 이렇게 작성했다. 예를 들어 mapper > first > *SQL.xml 와 mapper > first > second > *SQL.xml 은 다른 경로이다. (mapper 폴더 밑에 first, second 라는 이름의 폴더가 있는 경우를 의미)

우리는 앞으로 게시판에 관련된 쿼리만 작성하겠지만, 실제 프로젝트에서는 굉장히 많은 패키지가 생성되기 때문에 2,3단계로 구분된다. 그것을 유연성있게 대처하도록 해줬다.

마지막으로줄의 sqlSessionTemplate은 마이바티스 스프링 연동모듈의 핵심이다. SQLSessionTemplate은 SqlSession을 구현하고, 코드에서 SqlSessoin을 대체하는 역할을 한다.

5. DAO 작성

마지막으로 실제 소스에서 위에서 선언한 SqlSessionTemplate을 사용할 DAO를 만들어주자

1) src/main/java 폴더의 first > common 패키지 밑에 dao 패키지를 생성한다.

2) dao 패키지 안에 AbstractDAO.java를 생성한다.

3) AbstractDAO에 다음 소스를 작성한다.

public class AbstractDAO {
protected Log log = LogFactory.getLog(AbstractDAO.class);



@Autowired
private SqlSessionTemplate sqlSession;



protected void printQueryId(String queryId) {
if(log.isDebugEnabled()){
log.debug("\t QueryId \t: " + queryId);

}

}



public Object insert(String queryId, Object params){
printQueryId(queryId);
return sqlSession.insert(queryId, params);

}


public Object update(String queryId, Object params){
printQueryId(queryId);
return sqlSession.update(queryId, params);

}


public Object delete(String queryId, Object params){
printQueryId(queryId);
return sqlSession.delete(queryId, params);

}


public Object selectOne(String queryId){
printQueryId(queryId);
return sqlSession.selectOne(queryId);

}


public Object selectOne(String queryId, Object params){
printQueryId(queryId);
return sqlSession.selectOne(queryId, params);

}


@SuppressWarnings("rawtypes")
public List selectList(String queryId){
printQueryId(queryId);
return sqlSession.selectList(queryId);

}


@SuppressWarnings("rawtypes")
public List selectList(String queryId, Object params){
printQueryId(queryId);
return sqlSession.selectList(queryId,params);

}

}

우리가 앞에서 SqlSessionTemplate을 설정하였고, 이는 SqlSession을 대체한다고 이야기 했었다.

SqlSessionTemplate을 선언하고 여기에 Autowired 어노테이션(Annotation)을 통해서 xml에 선언했던 의존관계를 자동으로 주입하도록 하였다.

쿼리는 sqlSession.메서드를 호출하면 되는데, 여기서는 앞으로 개발할때, 좀 더 보기편하게 로그를 남기기위해서 AbstractDAO를 만들어서 insert, delete, update, select 메서드를 재정의 하였다.

실제 개발에서는 각 비즈니스 로직을 담당할 DAO를 생성하여 AbstractDAO를 상속받도록 할 계획이다.

Reference

http://addio3305.tistory.com/62

Comments