주니어레벨의 스프링MVC 개발순서
- DB -> MyBatis -> DAO -> Service -> Controller -> View
MyBatis(iBatis) 사용 방법 3가지
- XML 코드를 사용해서 SQL구문, DAO파일에서 XML코드를 호출해서 사용
- 애노테이션과 인터페이스를 사용해서 SQL구문 처리
- 장점: 별도의 DAO없이 개발 가능 (생산성 증가)
- 단점: 쿼리 수정이 필요한경우, 매번 컴파일 해야함.
- 인터페이스(애노테이션)와 XML을 같이 사용해서 SQL구문 처리
- 장점: 간단한 SQL 인터페이스로, 복잡한 SQL은 XML 파일을 사용하여 유연한 대처
- 단점: 개발자 마다 개발 방식의 차이가 발생 가능성 증가
MyBatis(iBatis) 사용 순서
포스팅에서는 위의 3가지 방식 중에 1번 방법을 사용해 볼 것이다.
- 필요한 라이브러리 준비
- DB생성 및 테이블 생성
- 도메인객체설계(DTO, VO), 클래스 생성
- DAO 인터페이스 생성
- 인터페이스에 사용할 기능들을 작성(명세)
- XML Mapper 생성, SQL구문 작성
- XML파일로 만들어진 Mapper의 위치설정
- XML파일안에 Mapper - DTD 지정
- SQL 구문 작성후 사용
- MyBatis에서 XML Mapper를 인식하도록 설정
- DAO 객체 구현
- 스프링을 활용한 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;
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; } 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
인터페이스 생성
- src > main > resource > mappers폴더생성 후
memberMapper.xml
파일 생성
- MyBatis 홈페이지 매핑된 SQL 구문 살펴보기에서 DOCTYPE 코드 복붙하기
- XML파일로 만들어진 Mapper의 위치설정은
root-context.xml
에 함
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itwillbs.mappers.memberMapper"> <select id="getTime" resultType="string"> select now() </select> </mapper>
<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
| <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:/Mybatis-config.xml" /> <property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml" /> </bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean>
|
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 { @Inject private SqlSession sqlSession; 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 { @Inject private MemberDAO mdao; @Test public void testDAO(){ System.out.println("테스트 : DAO객체생성 "+ mdao); } @Test public void testGetTime() throws Exception { System.out.println(mdao.getTime()); } }
|