본문 바로가기

웹 개발(OLD)/Spring Framework(OLD)

스프링+MyBatis+MySQL 연동 및 테스트(DAO 3단 구조로 구현)

- 전체 코드


BoardProject.zip




1. 먼저 MyBatis 라이브러리인 mybatis와 스프링와 MyBatis 를 연결할때 필요한 모듈인 mybatis-spring을 maven으로 설치해준다.

다음을 pom.xml에 추가한다.



2. MyBatis 와 스프링 연동 작업의 핵심은 Connect를 생성하고, 처리하는 SqlSessionFactory 의 존재이다. SqlSessionFactory 는 데이터베이스와의 연 결과 SQL 의 실행에 대한 모든 것을 가진 중요한 객체이다. 

스프링을 이용할 때는 SqlSessionFactory 를 생성해주는 특별한 객체를 설정할때 SqlSessionFactoryBean 이라는 클래스를 사용한다. 다음과 같이 root-context에 추가한다.

위 코드를 보면 이 클래스는 org.mybatis.spring.SqlSessionFactoryBean 즉, mybatis-spring모듈을 다운로드 받아야 사용이 가능하다.( 그래서 미리 다운 받아준 것)


3. 이후 MyBatis는 SQL Mapping 프레임워크로 별도의 설정파일을 가질 수 있다. 이를 이용하면 스프링의 설정과 별도로 사용하는 모든 MyBatis 의 설정기능을 활용할 수 있다. 따라서 src/main/resource 밑에 mybatis-config.xml파일을 생성한다.

만들어줬을때 초기 코드.


이 파일을 편하게 사용하기 위해서는 XML 파일의 DTD나 XML 스키마라는 것이 필요하다. 즉 다음과 같이

mybatis-config.xml파일 코드를 수정 해준다.




4. 이제 작성해둔 mybatis-config.xml 파일이 스프링이 동작할때 같이 동작하도록 설정해 주면 된다. 이는 SqlSessionFactoryBean의 configLocation 프러퍼티에다가 mybatis-config.xml의 경로를 지정해주면 된다.



5. 이제 연결 테스트를 해보면 된다.
즉, SqlSessionFactory에서 Session을 얻어올수 있는지 테스트하는 것이다. 이때는 try..catch..finally로 감싸주어야하는데 이후 이조차 하지않고 개발할수 있는 방법(SqlSessionTemplate 이용)도 소개하겠다.


test() 결과


sessionTest() 결과


자, 이제 스프링과 MyBatis, MySQL의 연동이 마무리 됐다.
MyBatis는 SQL Mapping 프레임워크라 했으니,  이제 SQL을 어떻게 Mapping시켜서 DB에 접근하여 쿼리처리를 하는지에 대한 테스트를 해주면 된다.



6. MyBatis 는 개발자가 직접처리하는 pstmt 의 ?에 대한 설정이나 ResultSet 을 이용한 처리가 이루어지기 때문에 기존 방식보다 생산성이 뛰어나다. 

MyBatis가 SQL을 처리하는 방식은 SQL문을 XML로 작성하고, SQL문을 사용하는 DAO클래스를 설계해서 SQL문을 호출하는 방식의 코드로 구성된다.
SQL문이 별도의 XML로 작성되기 때문에 SQL문의 수정이나 유지보수에 적합하나 코드양이 많아지고 복잡해질 수는 있다.
어쨌든 이제 XML로 쿼리를 개발해야할 차례이다. MyBatis를 XML을 사용해서 작성하는 개발 순서는 다음과 같다.

DB 테이블 생성
VO 클래스 설계
DAO 인터페이스 작성 - 실행해야 하는 기능을 인터페이스로 정의
XML Mapper의 생성과 필요한 DTD 추가 및 SQL문 작성
MyBatis에서 작성된 XML Mapper를 MyBatis가 동작할 때 인식하도록 설정
↓   
DAO인터페이스 구현하는 DAO 클래스 작성 - SqlSessionTemplate 이용
스프링상에 DAO 등록 및 테스트


7. 그럼 MySQL의 Workbench를 켜고 테이블 부터 만들어준다.



8. 도메인 클래스를 담을 org.zerock.domain 패키지를 새로 만들어준 후, 테이블에서 만든 컬럼명과 똑같은(왜?? 설명은 이후 그래야하는 이유가 나올 때 ) Instance variable을 갖는 MemberVO 클래스를 설계 해준다. ( getter & setter와 toString()을 오버라이딩한 코드는 길이상 잘린 상태. )


9. 이제 DAO를 구현해야하는데 이전에 DAO의 작업에서 가장 번거로운 작업이 뭔지를 생각해보자. 데이터베이스와의 연결을 맺고, 작업이 완료된 후에 연결을 close() 하는 작업이다. 이런 작업을 mybatis-spring 라이브러리에서 SqlSessionTemplate이라는 클래스를 제공한다. 이 클래스는 MyBatis의 SqlSession인터페이스를 구현한 클래스로 기본적인 트랜잭션을 관리하고 DB와의 연결과 종료를 책임진다. 즉, 이를 이용하면 개발자들이 직접 연결을 맺고 종료하는 작업을 줄일 수 있다.

다음과 같이 SqlSessionTemplate 은 SqlSessionFactory를 생성자로 주입해서 설정해준다.



10. 그리고 DAO에서 쿼리문을 이용하여 DB작업을 처리할 때 이용될 것을 설정해주어야한다.

 MyBatis에서는 SQL문을 저장하는 존재를 Mapper라 한다.


XML로 작성되는 Mapper파일의 경우 Java로 작성된 클래스와 경로를 분리해 주는 것이 유지보수에 있어서 필수적이다. 따라서 src/main/resources 밑에 mappers 폴더를 생성합니다.




작성한 mappers폴더에 memberMapper.xml 을 생성하고 쿼리를 개발하면 된다. 이때 XML Mapper를 작성할 때는 namespace라는 것의 설정에 조심해야한다. 클래스의 패키지와 유사한 용도로, MyBatis 내에서 원하는 SQL 문을 찾아서 실행할 때 동작하는 것이다.




MyBatis가 동작하면 작성한 XML Mapper를 인식해야만 정상적인 동작이 가능하므로, SqlSessionFactoryBean 의 mapperLocation 프로퍼티에 mappers 폴더의 .xml 들의 경로를 추가해주어야한다. 

이후 쿼리를 처리할 때 sqlSessionTeamplate.insert(), delete()등을 쓸수 있다. 이 메소드의 매개변수로 mappers폴더 안의 xml에 작성한 쿼리의 id값을 넣어주면 된다.


11. 이제 DAO 에서 실제로 실행할 기능들에 대한 스펙을 잡는 작업을 한다. 즉 인터페이스를 설계한다. 이때 DAO는 org.zerock.persistence라는 패키지를 새로 만들어서 이 안에서 작성한다.

DAO는 3단 구조로 설계한다.(아래에 구체적인 설명)



먼저 어떤 타입이던지 간에 DAO에서의 CRUD, List조회의 기능을 수행할 수 있도록 제네릭으로 인터페이스를 다음과 같이 GenericDAO<E,K>로 설계한다.


그리고 우리가 사용할 DAO는 tbl_member 테이블에 대한 접근을 할 것이므로 GenericDAO<E,K> 인터페이스를 상속하는 인터페이스 MemberDAO를 설계하고, 타입을 E는 MemberVO, K는 String으로 명시한다. (String은 테이블에서 컬럼 하나를 뽑아올 때 사용되는 key값이 String타입의 userid이므로 사용됨) 



이제 제네릭으로 설계한 DAO 인터페이스를 구현한다. 이때 DAO는 MyBatis 에게 DB 연결이나 SQL처리를 넘기므로 SqlSession 객체를 물고 있으면 된다. 


이제 위의 MemberDAO는 명세된 타입을 가져오기 위해 구현하고, GenericDAOImpl 은 DAO의 기본적인 기능인 CRUD와 리스트 조회를 구현해놓았기 때문에 상속받아서 MemberDAOImpl 클래스를 만든다. 

즉 여기서는 아무 코드를 작성하지 않아도 DB의 tbl_member 테이블에 CRUD와 List조회 기능을 모두 갖고있는 셈이 된 것이다.


근데 위의 MemberDAOImpl은 스프링에서 관리하는 bean이 되어야 하는데, 다음과 같이 S 표시가 없는 걸로 봐서 그렇지 않은 상태이다.





@Repository 라는 애노테이션을 추가하여 스프링한테 이 클래스가 DAO라는것을 알려주어야한다. 즉, 아래와 같이 코드를 한 줄만 수정하면, S 표시가 생겨난걸 확인할 수 있다.



12 그럼 이제 이 멤버다오 임플 코드가 잘 동작하는지 테스트해보면 된다.

먼저 다오 객체부터 스프링이 잘 주입하여 받아오는지 테스트해보자.


결과

결과부터보면 MemberDAO 타입의 dao를 Logger로 찍었는데 MemberDAOImpl이 출력된 것을 확인할 수있다.

MemberDAOImpl 클래스는 MemberDao 인터페이스를 구현하고 있으므로 MemberDAO 타입이다. 따라서 MemberDAOImple 클래스를 스프링이 관리하는 bean으로 둔 채로 위 코드처럼 MemberDAO 타입을 Inject하면 MemberDAO 타입인 MemberDAOImple 클래스의 객체가 주입되는 것이다. 따라서 dao를 찍어보면 MemberDAO 타입을 찍었지만 실제로는 MemberDAOImpl이 출력되는 것이다.


이제 작성한 Mapper들을 이용하여 SQL문을 처리해보자.


각각 코드 및 결과

- getTime

 




- register


 먼저 넣기전의 테이블의 빈 상태이다. 


넣은후 테이블 상태는 다음과 같이 값이 들어가있다.


찍힌 Logger 에서도 결과를 visual하게 확인할 수 있다. 




- get







- getList

리스트 테스트는 여러 데이터를 뽑을 수 있는 테스트를 위해 다음과 같이 register를 한 번 더 다른데이터로 수행한 후에 테스트한다.


찍힌 결과 Logger

테이블 상태


아 참 테스트 할 때 AbstractTest 를 상속받은 것은 테스트마다 써야하는 어노테이션과 Logger를 다음과 같이 추상클래스로 빼놨을 뿐 별 의미는 없다.



다음번엔 DB연결을 connection pool을 이용한 hicariCP를 적용해보고,

서비스 계층과 컨트롤러 계층을 구현하여 DAO와 연동시키자.

그리고 WAS없이 테스트할 수 있는 MockMvc를 이용하여 테스트 하는 것으로 마무리 짓기.

끝.