[Spring] MyBatis ์—ฐ๋™ ๋ฐ ์„ค์ •๋ฐฉ๋ฒ•

2021. 1. 21. 23:57ใ†๐Ÿ’ป ๊ฐœ๋ฐœ/Spring

MyBatis ํ”„๋ ˆ์ž„์›Œํฌ ํŠน์ง•

  • ๊ฐ„๋‹จํ•œ ์ž๋ฐ”์ฝ”๋“œ๋งŒ์œผ๋กœ DB ์—ฐ๋™์„ ์ฒ˜๋ฆฌํ•œ๋‹ค
  • SQL ๋ช…๋ น์–ด๋ฅผ ์ž๋ฐ” ์ฝ”๋“œ์—์„œ ๋ถ„๋ฆฌํ•˜์—ฌ XML ํŒŒ์ผ์— ๋”ฐ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค

์œ„์˜ ๋‘๊ฐ€์ง€ ํŠน์ง•์ด MyBatis์˜ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํŠน์ง•์ด๋ฉฐ, ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ JDBC ๊ธฐ๋ฐ˜์˜ DB์—ฐ๋™ ๋ฐฉ๋ฒ•๋ณด๋‹ค ํ›จ์”ฌ ๊ฐ„ํŽธํ•˜๋‹ค.

 

ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

Mybatis๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ„๋‹จํ•œ SQL์ฟผ๋ฆฌ๋ฌธ์„ ํ…Œ์ŠคํŠธํ•ด๋ณด์ž. 

 

๊ฐœ๋ฐœํ™˜๊ฒฝ

DBMS: Oracle Database 11g Express Edition Release 11.2.0.2.0
WEB Server: apache-tomcat-8.5.61 8
Language: Java EE 8
Framework: Spring 5.2.12.Release

 

1. MyBatis๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ 

๋‹ค์Œ์€ pom.xml์— ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์„ ์ถ”๊ฐ€ํ•˜๊ธฐ์œ„ํ•ด ์ž‘์„ฑํ•œ ์ฝ”๋“œ์ด๋‹ค.

<!-- pom.xml -->
	<properties>
		<spring.version>5.2.12.RELEASE</spring.version>
	</properties>
    
    	<!-- MyBatis ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
		<dependency>
    		<groupId>org.mybatis</groupId>
    		<artifactId>mybatis</artifactId>
    		<version>3.5.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
		<dependency>
    		<groupId>org.mybatis</groupId>
    		<artifactId>mybatis-spring</artifactId>
    		<version>2.0.5</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc8 -->
		<dependency>
    		<groupId>com.oracle.database.jdbc</groupId>
    		<artifactId>ojdbc8</artifactId>
         	<version>19.7.0.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
		<dependency>
    		<groupId>org.apache.commons</groupId>
    		<artifactId>commons-dbcp2</artifactId>
    		<version>2.7.0</version>
		</dependency>
  • spring-orm : ์Šคํ”„๋ง๊ณผ Mybatis๋ฅผ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • mybatis : Mybatis๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • mybatis-spring : mybatis์™€ ์Šคํ”„๋ง์„ ์—ฐ๋™์‹œํ‚ค๊ธฐ ์œ„ํ•œ ๋ชจ๋“ˆ
  • ojdbc8 : ์˜ค๋ผํด์‚ฌ์šฉ์œ„ํ•ด ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • commons-dbcp2 : ๋ฐ์ดํ„ฐ์†Œ์Šค ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (ํ†ฐ์บฃ์—์„œ connection pool์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์•„ํŒŒ์น˜์—์„œ ์ œ๊ณต)

2. SQL Mapper XMLํŒŒ์ผ ์ž‘์„ฑ

<!-- MembersMapper.xml -->
<?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="exam.spring.board.dao.MembersMapper">
	<select id="getMember" resultType="exam.spring.board.dto.Member">
		select id, name, password, email, join_date from members where id = #{id}
	</select>
	<insert id="addMember" parameterType="exam.spring.board.dto.Member">
		insert into members (id, name, password, email, join_date) values(#{id}, #{name}, #{password}, #{email}, sysdate)  
	</insert>
</mapper>

์ด SQL Mapper XMLํŒŒ์ผ์€ Mybatis์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํŒŒ์ผ์ด๋‹ค. XML ํŒŒ์ผ์•ˆ์— DB์—ฐ๋™์— ํ•„์š”ํ•œ SQL๋ช…๋ น์–ด๋“ค์ด ์ €์žฅ๋œ๋‹ค. SQL Mapper ํŒŒ์ผ์€ <mapper>๋ฅผ ๋ฃจํŠธ ์—˜๋ฆฌ๋จผํŠธ๋กœ ์‚ฌ์šฉํ•˜๊ณ  <insert>, <update>, <delete>, <select> ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ด์šฉํ•ด์„œ ํ•„์š”ํ•œ sql๊ตฌ๋ฌธ์„ ๋“ฑ๋กํ•œ๋‹ค.

 

์ฟผ๋ฆฌ๋ฌธ์„ ๋ณด๋ฉด id ์†์„ฑ๊ฐ’์ด ์žˆ๋Š”๋ฐ ์ด ๊ฐ’์ด ํ•ด๋‹น ์ฟผ๋ฆฌ๋ฌธ์˜ ์ด๋ฆ„์ด๋‹ค.

 

3. MyBatis ํ™˜๊ฒฝ์„ค์ • ํŒŒ์ผ ์ƒ์„ฑํ•˜๊ธฐ

<!-- configuration.xml -->
<?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">

XML ๋ฌธ์„œ์˜ ์œ ํšจ์„ฑ ์ฒดํฌ๋ฅผ ์œ„ํ•ด ํ•„์š”ํ•œ ์ฝ”๋“œ์ด๋‹ค.

 

4. SqlSession ๊ฐ์ฒด ์ƒ์„ฑํ•˜๊ธฐ

// MyBatisConfig.java

import java.io.IOException;
import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan(
		basePackages="exam.spring.board.dao",
		sqlSessionFactoryRef="sqlSessionFactoryBean"
)
public class MyBatisConfig {
	@Bean
	public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource, ApplicationContext applicationContext) throws IOException {
		SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
		factoryBean.setDataSource(dataSource);
		factoryBean.setConfigLocation(applicationContext.getResource("classpath:mybatis/configuration.xml"));
		factoryBean.setMapperLocations(applicationContext.getResources("classpath:mybatis/mappers/MembersMapper.xml"));
		// mappers/**/*.xml -> mappers ์ดํ•˜ xml ํ™•์žฅ์ž๋ฅผ ๊ฐ–๋Š” ๋ชจ๋“  ๊ฒฝ๋กœ๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค 
		return factoryBean;
	}
}

SqlSessionFactoryBean ๊ฐ์ฒด๊ฐ€ ์‹ค์งˆ์ ์ธ ๋งคํ•‘์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฐ์ฒด์ด๋‹ค. 

 

=> ์ด ๋ถ€๋ถ„์ด ํ•ต์‹ฌ์ฝ”๋“œ์ธ๋ฐ, SqlSessionFactoryBean๋Š” ์œ„์™€ ๊ฐ™์ด 3๊ฐ€์ง€ ์ •๋ณด๋ฅผ ๋“ฑ๋ก์‹œํ‚จ๋‹ค.

  • DataSource ์ •๋ณด (์„ค์ •๊ด€๋ จ๋œ ํŒŒ์ผ์€ config ํŒจํ‚ค์ง€์— ๋”ฐ๋กœ ์ƒ์„ฑํ•ด์ฃผ์—ˆ๋‹ค)
  • MyBatis ์„ค์ • ์ •๋ณด
  • Mapper ์„ค์ • ์ •๋ณด → ์ด๊ณณ์— SQL๋ฌธ์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ์ ธ ์žˆ๋‹ค

5. DataSource ์ •๋ณด ๋“ฑ๋ก

๋‹ค์Œ์€ DB์ปค๋„ฅ์…˜ ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ์žˆ๋Š” DataSource์ด๋‹ค. 

// ApplicationConfig.java

import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;

@Configuration
@ComponentScan(basePackages = {"exam.spring.board.dao","exam.spring.board.service"})
@Import({MyBatisConfig.class})
public class ApplicationConfig {
	@Bean
	public DataSource dataSource() { 
		SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
		dataSource.setDriverClass(oracle.jdbc.driver.OracleDriver.class);
		dataSource.setUrl("jdbc:oracle:thin:@localhost:1521:xe");
		dataSource.setUsername("master");
		dataSource.setPassword("1004");
		return dataSource;
	}
}

Mybatis๋Š” ํŠน์ • DBMS๋กœ๋ถ€ํ„ฐ ์ปค๋„ฅ์…˜์„ ํš๋“ํ•˜๊ณ  DB์—ฐ๋™์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋ฐ˜๋“œ์‹œ DataSource ์ •๋ณด๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

 

6. DAO & DTO ํด๋ž˜์Šค ์ž‘์„ฑ

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๋™์„ ์ฒ˜๋ฆฌํ•  DTO์™€ DAOํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฒƒ์ด๋‹ค.

์œ„์˜ Mapper ์„ค์ •ํŒŒ์ผ์—์„œ ๋“ฑ๋กํ•œ ์ฟผ๋ฆฌ๋ฌธ์˜ id ์†์„ฑ๊ฐ’์„ ๋ฉ”์„œ๋“œ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. 

// MemberMapper.java
package exam.spring.board.dao;

import org.apache.ibatis.annotations.Mapper;
import exam.spring.board.dto.Member;

@Mapper
public interface MembersMapper {
	public Member getMember(String id);
	public void addMember(Member member);
}

 

๋‹ค์Œ์€ ๋ฐ์ดํ„ฐ ์ „์†ก์„ ์ฒ˜๋ฆฌํ•  DTO๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ๊ฒƒ์ด๋‹ค. 

XMLํŒŒ์ผ์— ์ €์žฅ๋œ SQL ๋ช…๋ น์–ด์— ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’๋“ค์„ ์ „๋‹ฌํ•˜๊ณ  ์‹คํ–‰๊ฒฐ๊ณผ๋ฅผ ๋งคํ•‘ํ•œ๋‹ค. 

// Member.java 

public class Member {
	private String id;
	private String name;
	private String password;
	private String email;
	private String joinDate;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
    
	...
	
	@Override
	public String toString() {
		return "Member [id=" + id + ", name=" + name + ", password=" + password + ", email=" + email + ", joinDate="
				+ joinDate + "]";
	}
	
}

 

7. ํ…Œ์ŠคํŠธ ํด๋ผ์ด์–ธํŠธ ์ž‘์„ฑ ๋ฐ ์‹คํ–‰

๋‹ค์Œ์€ DAOํด๋ž˜์Šค์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค.

DAO ํŒŒ์ผ๊ณผ ๋™์ผํ•œ ํŒจํ‚ค์ง€ ๊ฒฝ๋กœ๋กœ ์„ค์ •ํ•ด์„œ ํ…Œ์ŠคํŠธํ•ด๋ณธ๋‹ค. 

 

mybatis ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด jUnit์„ ์‚ฌ์šฉํ–ˆ์œผ๋ฉฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด junit ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ถˆ๋Ÿฌ์™€์•ผํ•œ๋‹ค. 

	<!-- junit -->
	<!-- https://mvnrepository.com/artifact/junit/junit -->
	<dependency>
   		<groupId>junit</groupId>
   		<artifactId>junit</artifactId>
   		<version>4.13.1</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-test</artifactId>
		<version>${spring.version}</version>
	</dependency>
  • junit : junit์€ ์ž๋ฐ”์šฉ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ์„ ์œ„ํ•œ ์‚ฐ์—… ํ‘œ์ค€ ํ”„๋ ˆ์ž„์›Œํฌ๋‹ค.
  • spring-test : ์Šคํ”„๋ง์— Mybatis๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์—ฐ๋™๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์šฉ๋„

 

์ฟผ๋ฆฌ๋ฌธ์—์„œ insert๊ตฌ๋ฌธ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•ด๋ณด์ž

// MembersMapperTest.java

package exam.spring.board.dao;

import org.junit.Assert;
...
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import exam.spring.board.config.ApplicationConfig;
import exam.spring.board.dto.Member;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ApplicationConfig.class})
public class MembersMapperTest {

	@Autowired
	MembersMapper membersMapper;

	@Test
	public void addMember() throws Exception{
		Member testMember = new Member();
		testMember.setId("test");
		testMember.setName("ํ…Œ์ŠคํŠธ");
		testMember.setPassword("test");
		testMember.setEmail("test@test.com");
		
		membersMapper.addMember(testMember);
		Assert.assertNotNull(membersMapper.getMember("test"));
	}
}

 

8. ์‹คํ–‰๊ฒฐ๊ณผ


์ „์ฒด ์†Œ์Šค์ฝ”๋“œ

https://github.com/jiyoung-dev/TIL/tree/master/Spring/MVCmodel