웹(WEB)/spring-framework

[spring] MyBatis 사용(설정)하기

고품격미식가 2019. 9. 8. 15:06

1. MyBatis란 무엇인가?

 

http://www.mybatis.org/mybatis-3/index.html

 

mybatis – MyBatis 3 | Introduction

What is MyBatis? MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results. MyBatis can use

www.mybatis.org

위 사이트에 마이바티스에 대한 간략한 소개가 나와있어 가져왔다.

What is MyBatis?

MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results. MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJOs (Plain Old Java Objects) to database records.

 

다행히도(?) 사이트내 한글번역을 지원한다.

마이바티스는 무엇인가?

마이바티스는 개발자가 지정한 SQL, 저장프로시저 그리고 몇가지 고급 매핑을 지원하는 퍼시스턴스 프레임워크이다. 마이바티스는 JDBC로 처리하는 상당부분의 코드와 파라미터 설정및 결과 매핑을 대신해준다. 마이바티스는 데이터베이스 레코드에 원시타입과 Map 인터페이스 그리고 자바 POJO 를 설정해서 매핑하기 위해 XML과 애노테이션을 사용할 수 있다.

.................

 

기존에 JDBC를 이용하여 프로그래밍을 하는 방식은 프로그램 소스안에 SQL문을 작성하여,

connection을 맺고, select문을 날려서 ResultSet이 나오고, 그걸 rs.next()등을 이용하여 하나씩 받아오는 그런 방식이었다.

이는 SQL의 변경 등이 발생하면, 프로그램을 수정해야 했기 때문에 유연성이 좋지 못했다.

마이바티스에서는 SQL문을 xml파일에 따로 작성하기 때문에, SQL의 변경 등이 발생해도 수정이 용이하고, 가독성이 좋은 장점을 가진다.

 

2. MyBatis 필요 라이브러리

 

추가합시다.

//공통필수 라이브러리
<!-- mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>

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

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

<!-- spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.1.5.RELEASE</version>
</dependency>

//mysql을 사용할 경우
<!-- mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.31</version>
</dependency>

//oracle의 경우
<!-- ojdbc14 -->
<dependency>
    <groupId>com.oracle</groupId>
    <artifactId>ojdbc14</artifactId>
    <version>10.2.0.4.0</version>
</dependency>

 

3. MyBatis 설정

 

root-context.xml에 다음의 소스를 추가합니다.

<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>

 

 

지금까지 <bean>객체를 3개 만들었습니다. (DI의 개념을 알면 이해하기 좀 수월하겠지만, 나도 아직 잘 모른다. 무튼) 

즉, <bean>으로 등록만하면

BasicDataSource = new BasicDataSource();

SqlSessionFactoryBean = new SqlSessionFactoryBean();

SqlSessionTemplate = new SqlSessionTemplate();

이렇게 길게 나열하지 않아도 객체를 자동으로 등록해주고, 그 객체에 대한 관리를 스프링에 맞기겠다! 라고 정의를 해주는 겁니다.

 

쉽게 생각하면 물건을 납품하는 공장을 만들었습니다.

<property name="mapperLocations" value="classpath:/mapper/**/*_SQL.xml" /> 에 맵퍼경로가 설정됩니다.

classpath:/mapper/**/*_SQL.xml 이 말은, 컴파일된 경로에서 mapper 라는 폴더안에,  /**/ 라는 그 다음폴더를 포용한다는 의미입니다.

예를들어 mapper안에 board라는 폴더가 있으면, mapper안 board폴더안에 땡땡떙땡_SQL.xml 파일을 찾아주세요. 라는 의미입니다.

sqlSessionTemplate는 공장안에 물건을 찍어내는 그런 기계같은 녀석입니다.

 

4. MyBatis 사용

이제 위에서 선언한 sqlSessionTemplate을 사용할 DAO(Data Access Object)를 만들어 줘야한다. DAO는 비즈니스 로직을 모듈화 하는 방법이다.

 

 

dao, service, serviceImpl, vo 필요한 클래스들을 만들어 줬습니다.

 

 

 

QnaService.java는 인터페이스로 생성했습니다. 인터페이스에는 메소드를 정의하지요.

 

 

QnaService를 임플리먼트 받은 QnaServiceImpl은 어디서든 selectQnaList를 사용할 수 있겠죠? 그 사용은 재정의를 할 수도 있고 뭐 그렇습니다. 그럼 정의를 해줘야겠지요. 실제 비즈니스 로직이 들어가는 부분인 것이죠. 아직은 가공따윈 하지않고 그냥 통로역할만 하게끔 바로 리턴시키겠습니다.

참고로, @Autowired는 private QnaDAO qnaDAO = new QnaDAO(); 와 같습니다.

 

 

 

근데 impl은 db의 값을 가져오기도 하지만, 정형화된 데이터를 다시 컨트롤러에 보내주는 역할을 하기도 합니다. 일종의 중간역할자를 하는 버스라고 할 수 있습니다. 그럼 그 DB와 계속 통신만 하는 녀석이 바로 DAO라는 녀석입니다.

 

자, 컨트롤러도 db의 값을 impl에서 받아야 겠죠?

컨트롤러에서 어떻게 받아야하고 어떻게 보내야 할까요?

보면 클라이언트가 /qna/list url로 요청을 합니다. 쭉 소스를 읽다가 

List<Map<String, Object>> rsList = qnaService.selectQnaList(paramVO); 이 소스를 만나게 되면 qnaService에 selectQnaList라는 메소드를 실행할 것입니다. qnaService는 인터페이스니, 실제 로직 정의된 임플로 갔더니 역할이 나중엔 qnaDAO객체의 selectQnaList라는 녀석도 실행시킵니다. DAO와서 selectQnaList를 확인해보면 db랑 연결이 되는걸 알 수 있습니다. 일종의 꼬리물기입니다. 메소드안에 메소드가 있고 또 메소드가 있고 나중엔 db와 통신하는 메소드가 있고, 근데 그게 class를 나눠서 역할을 나누는겁니다.

 

 

한마디로, 서비스는 컨트롤러와 impl의 연결을

impl은 호출된 서비스와 dao를

dao는 db와 통신합니다.

그림으로 살펴보면 다음과 같습니다.

 

 

자 그럼 DAO는 DB와 연결을 해야 하겠죠? 모든 정보는 아까 sqlSessionTemplate에 있습니다.

id로 그 객체를 끌어다가 QnaDAO에서 사용하기 위해서 저런 어노테이션과 private SqlSessionTemplate sqlSessionTemplate; 에 만들어진 객체를 주입 시키기 위해서 

@Resource(name="sqlSessionTemplate") 객체를 가져와서

private SqlSessionTemplate sqlSessionTemplate; 에 넣어주세요.

이미 만들어진 녀석을 id로 끌어와야 되기때문에 각각의 역할에 맞게 이번엔 @Autowired대신에, @Resource라는 어노테이션을 사용했습니다.

 

자 이제, mapper파일은 리소스폴더 안에 만들어야 합니다.

 

 

qna_SQL.xml 소스입니다. qna테이블로 부터 *(모든 데이터)를 가져오라는 쿼리문을 작성했습니다.

<mapper namespace="qna"> 이건 이 xml의 id라고 생각하면 된다.

qna와 selectQnaList가 만나 두개의 아이디는 .으로 연결한다. qna.selectQnaList 이런식이다.

 

 

VO에는 title과 contents 두가지 변수를 만들었고,

 

 

데이터를 꺼내오기 위해 DB에 데이터를 미리 입력해 놓았다.

 

 

이제, 데이터를 잘 가져오는지 눈으로 확인하기 위해서 컨트롤러에 Sys.out으로 찍어줘보자.

 

 

성공이다.