[스프링SPRING]주니어레벨의 스프링MVC 개발순서, MyBatis(iBatis) 사용 방법 3가지

주니어레벨의 스프링MVC 개발순서

  • DB -> MyBatis -> DAO -> Service -> Controller -> View




MyBatis(iBatis) 사용 방법 3가지

  1. XML 코드를 사용해서 SQL구문, DAO파일에서 XML코드를 호출해서 사용
  2. 애노테이션과 인터페이스를 사용해서 SQL구문 처리
    • 장점: 별도의 DAO없이 개발 가능 (생산성 증가)
    • 단점: 쿼리 수정이 필요한경우, 매번 컴파일 해야함.
  3. 인터페이스(애노테이션)와 XML을 같이 사용해서 SQL구문 처리
    • 장점: 간단한 SQL 인터페이스로, 복잡한 SQL은 XML 파일을 사용하여 유연한 대처
    • 단점: 개발자 마다 개발 방식의 차이가 발생 가능성 증가




MyBatis(iBatis) 사용 순서

포스팅에서는 위의 3가지 방식 중에 1번 방법을 사용해 볼 것이다.

  1. 필요한 라이브러리 준비
  2. DB생성 및 테이블 생성
  3. 도메인객체설계(DTO, VO), 클래스 생성
  4. DAO 인터페이스 생성
  5. 인터페이스에 사용할 기능들을 작성(명세)
  6. XML Mapper 생성, SQL구문 작성
    • XML파일로 만들어진 Mapper의 위치설정
    • XML파일안에 Mapper - DTD 지정
    • SQL 구문 작성후 사용
  7. MyBatis에서 XML Mapper를 인식하도록 설정
  8. DAO 객체 구현
  9. 스프링을 활용한 DAO테스트(Junit)




DB 생성 및 테이블 생성

아래와 같이 테이블을 생성해준다.




도메인객체인 MemberVO.java 생성

Domain(도메인)이란? 물리적인 환경으로 분리가 가능한 단위

  • 개발(프로젝트)에서 가장 중요한 용어(단어)이고 주로 명사이다.
    • 예를 들어 회원, 상품, 글, 주문, 배송, 댓글 … (1차 도메인)
    • 회원-가입, 탈퇴, 수정 … (2차 도메인)
  • 즉 DB테이블로 구분할 수 있는 단위
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
32
33
34
35
36
37
38
39
40
41
package com.itwillbs.domain;

import java.sql.Timestamp;

public class MemberVO {
private String userid;
private String userpw;
private String username;
private String useremail;
private Timestamp regdate;
private Timestamp updatedate;

//생성자 2개 : 기본생성자, 멤버변수를 인자로 전부를 가진 생성자
public MemberVO() {}
public MemberVO(String userid, String userpw, String username, String useremail, Timestamp regdate,
Timestamp updatedate) {
super();
this.userid = userid;
this.userpw = userpw;
this.username = username;
this.useremail = useremail;
this.regdate = regdate;
this.updatedate = updatedate;
}

//get() set()메서드 생성
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}

(중략)

@Override
public String toString() {
return "MemberVO [userid=" + userid + ", userpw=" + userpw + ", username=" + username + ", useremail="
+ useremail + ", regdate=" + regdate + ", updatedate=" + updatedate + "]";
}
}




MemberDAO.java 인터페이스 생성

  • 해당 도메인에 관련된 기능 선언
  • 기능을 구현하는 것이 아니라 기능을 선언만 한다. 구현은 DAO 구현클래스에서 진행한다.
1
2
3
4
5
6
package com.itwillbs.persistence;

public interface MemberDAO {
//해당 도메인에 관련된 기능 선언
public String getTime();
}




XML Mapper 생성, SQL구문 작성 : memberMapper.xml 인터페이스 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>

<!-- DTD지정 -->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- SQL 구문 작성후 사용 -->
<mapper namespace="com.itwillbs.mappers.memberMapper">
<select id="getTime" resultType="string">
select now()
</select>
</mapper>

<!-- DAO패키지(com.itwillbs.persistence)와 연결 -->
<context:component-scan base-package="com.itwillbs.persistence" />




MyBatis에서 XML Mapper를 인식하도록 설정

  • root-context.xml파일에 위에서 만든 mapper파일을 연결시켜준다.
  • SqlSessionTemplate 객체 : DB연결, 사용후에는 자원해제 (close()) 처리해주는 객체
    • mybatis-spring 라이브러리에 포함되어있다.
    • SqlSession 인터페이스를 구현한 객체이다.
      • SqlSession인터페이스는 기본적인 트랜잭션, 쓰레드 처리의 안정성 보장, 디비 연결/해체처리
  • SqlSessionFactory 객체와 SqlSessionTemplate객체의 차이점
    • SqlSessionFactory객체는 Connection + MyBatis 객체연결 역할, DB해제는 못하고 Connection해제만 가능
    • SqlSessionTemplate객체는 DB연결/해제(pstmt, resultset포함 해제가능) 역할
  • 크기가 작은 객체들을 먼저 생성하고 크기가 큰 객체들을 나중에 생성한다. 생성한 큰 객체들안에 작은 객체들을 주입한다.
    • 처음부터 큰 객체를 만들면 되는데 왜 작은 객체부터 만드는걸까?
    • 코드의 유지보수성때문에.
    • 작은 기능을 사용할때는 작은 클래스를 사용할 수 있도록 모듈화하는 것이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- SqlSessionFactory 객체 (Connection + MyBatis 객체연결 역할, DB해제는 못하고 Connection해제만 가능)-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 위에서 생성된 객체를 주입하기 위해서는 value가 아니라 ref를 통해서 주입해야한다 -->
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:/Mybatis-config.xml" />
<!-- Mapper와 연결 -->
<property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml" />
</bean>
<!-- SqlSessionFactory 객체 end-->

<!-- SqlSesstionTemplate 객체 (DB연결/해제(pstmt, resultset포함 해제가능) 역할)-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
<!-- 바로 위에 있는 sqlSessionFactory객체를 생상자 의존주입 -->
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<!-- SqlSesstionTemplate 객체 end-->




DAO 객체 구현 : MemberDAOImpl.java 객체 생성

  • 테스트를 위해서 @Repository 사용
    • DAO객체를 스프링으로 인식할 수 있도록 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.itwillbs.persistence;

import javax.inject.Inject;

import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;

@Repository
public class MemberDAOImpl implements MemberDAO {

//DB연결 (xml에서 만들어진 객체를 가져다 사용하고자함 = 의존 주입)
@Inject
private SqlSession sqlSession; //mapper위치까지 접근 가능 but mapper가 여러개일수있음 => mapper구분필요

//mapper구분하는 값 namespace
private static final String namespace = "com.itwillbs.mappers.memberMapper";

@Override
public String getTime() {
String result = sqlSession.selectOne(namespace+".getTime"); //괄호안에 쿼리구문 넣으면 됨
return result;
}
}




스프링을 활용한 DAO테스트(Junit) : MemberDAOTest.java 생성

  • @RunWith + @ContextConfiguration => 스프링으로 테스트하겠다는 의미
  • @RunWith + @ContextConfiguration + @WebAppConfiguration => 스프링MVC로 테스트하겠다는 의미
  • root-context.xml에 DAO객체를 연결해줘야 테스트 가능하다.
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
package com.itwillbs.test;

import javax.inject.Inject;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.itwillbs.persistence.MemberDAO;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {"file:src/main/webapp/WEB-INF/spring/root-context.xml"})
public class MemberDAOTest {

//DB처리객체 생성 ->MemberDAO 인터페이스라서 객체 생성할 수없다 -> 의존 주입 @Inject 추가
@Inject
private MemberDAO mdao;

@Test
public void testDAO(){
System.out.println("테스트 : DAO객체생성 "+ mdao);
}

@Test
public void testGetTime() throws Exception {
//DAO getTime() 메서드 사용가능한지 테스트
System.out.println(mdao.getTime());
}
}