# Spring+MyBatis+MySQL 연동하기
- 1. 필요한 라이브러리 추가.
Spring과 MyBatis 사이에 접착제 역할을 하는 My-Batis-Spring 모듈이 필요한데 여기에 필요한 각종 라이브러리들을
pom.xml에 추가한다.
#1 Mybatos
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
#2 MyBatis-spring
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.2</version>
</dependency>
#3 spring-jdbc
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
#4 Spring-tset
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
- 2. root-context.xml 파일에 namespace를 추가
네임스페이스를 추가해주지 않으면 스프링에서 사용 가능한 XML 태그를 인식하지 못하는 문제가 발생한다.(?)
- 3. DataSource 설정
스프링과 MyBatis를 같이 사용하는 경우 주로 스프링의 설정으로 JDBC 연결을 처리가 많기 때문에
spring-jdbc모듈을 이용하여 root-context.xml에 다음과 같이 DataSource라는 것을 추가한다.
DataSource는 JDBC 커넥션을 처리하는 기능을 가지고 있기 때문에 DB와 연동시 반드시 필요하다.
#root-context.xml 에 추가할내용
1
2
3
4
5
6
|
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
<property name="url" value="jdbc:log4jdbc:mysql://127.0.0.1:3306/book_ex"></property>
<property name="username" value="root"></property>
<property name="password" value="root_password"></property>
</bean>
|
cs |
#ETC : DataSource Test : 스프링은 하나라도 설정이 잘못되면 정상적으로 로딩되지 않기에 변경된 설정에 대해서 바로바로 테스트해주는 것이 좋다.
따라서 다음과 같이 DataSource 설정에 대한 Test code를 작성한다.
#DataSource 테스트 코드
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
|
package org.zerock.controller;
import java.sql.Connection;
import javax.inject.Inject;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/**/*.xml"})
public class DataSourceTest {
@Inject
private DataSource ds;
@Test
public void testconnection() throws Exception{
try(Connection con = ds.getConnection()) { // try() { TODO } catch (Exception e) { TODO} 형태를 try -with구문이라하며 자동으로 Connection 객체가 clse()될 수 있도록 작성 한 것이다.
System.out.println("test");
System.out.println("connection 객체출력 : " + con);
} catch (Exception e) {
e.printStackTrace();
}
}
}
|
cs |
- 4. SqlSessionFactory 객체 설정
MyBatis와 스프링 연동 작업에서의 핵심은 Connection을 생성하고 처리하는 SqlSessionFactory 이다.
SqlSessionFactory는 DB연결과 SQL의 실행에 대한 모든 것을 가지고 있는 중요한 객체이다.
아래와 같이 SqlSessionFactoryBean 클래스를 빈으로 등록한다.
1
2
3
4
|
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:/mybatis-config.xml"></property>
</bean>
|
cs |
위 내용을 보면 configLocation을 설정하는 property가 보이는데 따라서 mybatis-config.xml 파일을 추가해야한다.
- 5. mybatis-config.xml 파일 추가
MyBatis는 SQL Mapping 프레임 워크로서 별도의 설정파일을 가진다.
mybatos-config.xml 파일을 src/main/resources 디렉토리에 생성해주고 내용은 아래와 같이 작성한다.
1
2
3
|
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration></configuration>
|
cs |
https://mybatis.org/mybatis-3/configuration.html 을 참조하면 더 자세하게 xml에 작성할 내용을 작성할 수 있다.
여기까지만 수행하면 MyBatis+Spring+MySQL 연동 설정이 끝난 것이다.
제대로 설정이 되었는지 확인하기 위해서 MyBatis 연결 테스트 코드를 아래와 같이 작성 해보자.
#MyBatis 연결 테스트코드
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
|
package org.zerock.controller;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.inject.Inject;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/**/*.xml" })
public class MyBatisTest {
@Inject
public SqlSessionFactory sqlFactory;
@Test
public void testFactory() {
System.out.println(sqlFactory);
}
@Test
public void testSession() throws Exception {
try (SqlSession session = sqlFactory.openSession()) {
System.out.println("session 객체출력 : " + session);
} catch (Exception e) {
e.printStackTrace();
}
}
}
|
cs |
이제 다음은 실제로 MyBatis를 xml을 통해서 sql을 사용해보도록 한다.
# XML을 통해서 DAO에 사용할 실제 SQL query 사용해보기
1. DAO 인터페이스 작성
일반적인 경우 DAO는 persistence라는 패키지에 작성하며 DAO인터페이스를 해당 패키지 내에 작성한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package org.zerock.persistence;
import org.zerock.domain.BoardVO;
import java.util.List;
public interface BoardDAO {
public void create(BoardVO vo) throws Exception;
public BoardVO read(Integer bno) throws Exception;
public void update(BoardVO vo) throws Exception;
public void delete(Integer bno) throws Exception;
public List<BoardVO> listAll() throws Exception;
}
|
cs |
2. XML Mapper 작성
DAO 클래스를 사용하는 실질적인 SQL 문이 작성되는 Mapper.xml 파일을 만들어준다.
xxxxMapper.xml과 같이 Mapper xml파일들은 src/main/resources 경로에 생성해주도록 한다.
다음은 간단한 게시판 페이지에 쓰일 DAO에 사용하는 SQL이 작성된 Mapper.xml 파일 예시이다.
#boardMapper.xml
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
|
<?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="org.zerock.mapper.BoardMapper">
<insert id="create">
insert into tbl_board (title, content, writer) values(#{title}, #{content}, #{writer})
</insert>
<select id="read" resultType="org.zerock.domain.BoardVO">
select bno, title, content, writer, regdate, viewcnt
from tbl_board
where bno = #{bno}
</select>
<update id="update">
update tbl_board set title = #{title}, content = #{content}
where bno = #{bno}
</update>
<delete id="delete">
delete from tbl_board where bno = #{bno}
</delete>
<select id="listAll" resultType="org.zerock.domain.BoardVO">
<![CDATA[
select
bno, title, content, writer, regdate, viewcnt,
from
tbl_board
where bno > 0
order by bno desc, regdate desc
]]>
</select>
</mapper>
|
cs |
3. XML-Mapper 인식 설정
MyBatis가 위에서 작성된 Mapper.xml 파일을 인식하기 위해서 root-context.xml 파일에서
sqlSessionFactory 빈을 등록한 곳에 mapper.xml파일이 어디에 존재하는지 알려주기 위해서
mapperlocation 속성을 추가해줘야한다.
1
2
3
4
5
|
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:/mybatis-config.xml"></property>
<property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"></property>
</bean>
|
cs |
<property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"></property>
요 한줄이 추가 된 것을 확인 할 수 있다.
4. SqlSessionTemplate 설정
DAO 작업에서 제일 귀찮은 것이 db관련 작업이후 close()해주는 것이다. 그런데 mybatis에서는 이것을 처리 해주는 sqlSesstionTemplate라는 클래스는 제공하는데 이 클래스의 객체를 쓰겠다고 설정하는 것이다.
즉 , SqlSessionTemplate 객체를 스프링 컨테이너의 bean으로 등록해주는 것이다.
1
2
3
|
<bean id="sqlSession" name="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean>
|
cs |
5. 구현 클래스 작성하고 스프링에 Bean으로 등록해주기.
DAO interface에 대한 구현 클래스를 작성해준다. 이때 구현클래스를 @Repository 어노테이션을 설정해주더라도 스프링에서 해당 패키지 디렉토리를 스캔하지 않으면 빈으로 등록되지 않기 때문에 root-context.xml 에서 아래와 같이
특정 디렉토리를 스캔하라는 태그를 작성해준다.
#root-context.xml 추가할 내용
1
|
<context:component-scan base-package="org.zerock.persistence"></context:component-scan>
|
cs |
#구현 클래스 작성 예시
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
42
43
|
package org.zerock.persistence;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import org.zerock.domain.BoardVO;
import javax.inject.Inject;
import java.util.List;
@Repository
public class BoardDAOImpl implements BoardDAO {
@Inject
private SqlSession session;
private static String namespace = "org.zerock.mapper.BoardMapper";
@Override
public void create(BoardVO vo) throws Exception {
session.insert(namespace+".create", vo);
}
@Override
public BoardVO read(Integer bno) throws Exception {
return session.selectOne(namespace+".read", bno);
}
@Override
public void update(BoardVO vo) throws Exception {
session.update(namespace+".update", vo);
}
@Override
public void delete(Integer bno) throws Exception {
session.update(namespace+".delete", bno);
}
@Override
public List<BoardVO> listAll() throws Exception {
return session.selectList(namespace+".listAll");
}
}
|
cs |
# Etc : 작성된 BoardDAO 테스트
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
42
43
44
45
46
47
48
49
50
51
52
|
package test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.zerock.domain.BoardVO;
import org.zerock.persistence.BoardDAO;
import javax.inject.Inject;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/**/*.xml"})
public class BoardDAOTest {
private static final Logger logger = LoggerFactory.getLogger(BoardDAOTest.class);
@Inject
private BoardDAO dao;
@Test
public void testCreate() throws Exception {
BoardVO boardVO = new BoardVO();
boardVO.setTitle("초기 제목입니다.");
boardVO.setContent("초기 내용입니다.");
boardVO.setWriter("user000");
dao.create(boardVO);
}
@Test
public void testRead() throws Exception{
logger.info(dao.read(5).toString());
}
@Test
public void testUpdate() throws Exception{
BoardVO boardVO = new BoardVO();
boardVO.setBno(5);
boardVO.setTitle("제목이 수정되었습니다.");
boardVO.setContent("내용이 수정되었습니다.");
dao.update(boardVO);
}
@Test
public void testDelete() throws Exception{
dao.delete(1);
}
}
|
cs |
#Etc2 : table 작성 sql 문
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
CREATE TABLE tbl_member(
useridbook_exbook_ex VARCHAR(50) NOT NULL,
userpw VARCHAR(50) NOT NULL,
username VARCHAR(50) NOT NULL,
email VARCHAR(100),
regdate TIMESTAMP DEFAULT NOW(),
updatedate TIMESTAMP DEFAULT NOW(),
PRIMARY KEY(userid)
);
CREATE TABLE tbl_board(
bno INT NOT NULL AUTO_INCREMENT,
title VARCHAR(200) NOT NULL,
content TEXT NULL,
wirter VARCHAR(50) NOT NULL,
regdate TIMESTAMP NOT NULL DEFAULT NOW(),
viewcnt INT DEFAULT 0,
PRIMARY KEY (bno)
);
ALTER TABLE tbl_board CONVERT TO CHARSET UTF8;
|
cs |
결과확인
'Spring' 카테고리의 다른 글
Spring - An illegal reflective access operation has occurred Illegal reflective access by org.apache.ibatis.reflection.Reflector (0) | 2022.01.21 |
---|---|
Spring - Json 반환 (0) | 2022.01.20 |
ContextConfiguration cannot be resolved to a type 에러 (0) | 2022.01.19 |
Spring - Junit Test (0) | 2022.01.17 |
Spring - Component vs Bean vs Configuration (0) | 2022.01.12 |