코딩하는 문과생

[Spring] Spring 프레임워크(8) - MyBatis 본문

웹 프로그래밍/Spring

[Spring] Spring 프레임워크(8) - MyBatis

코딩하는 문과생 2020. 3. 10. 18:12

<참고>

강의는 2016년에 제작되었다. 따라서 MySQL과 Spring연동시 고려해야할 사항이 있다.
가령 pom.xml에 추가되는 mysql의존성이던지 db.url에 "serverTimezone=UTC"을 추가해야하는 등 고려사항이 존재한다.


[MyBatis]

자바 오브젝트와 SQL문 사이의 자동 맵핑 기능을 지원하는 Object Mapper(ORM x)이다.

  • SQL을 별도의 파일로 분리시켜준다.
  • 개발자가 익숙한 SQL을 그대로 이용할 수 있다.
  • 쉬운 접근성과 코드의 간결함: XML형태로 서술된 JDBC 코드다.
  • 개발자는 Application과 mapping File만 작성하면 된다.

Database의 Connection = MyBatis의 SqlSession

 

ex. MyBatis 설정

- pom.xml 의존성 추가

	<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
	<dependency>
	    <groupId>org.mybatis</groupId>
	    <artifactId>mybatis</artifactId>
	    <version>3.4.4</version>
	</dependency>
	
	<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
	<dependency>
	    <groupId>org.mybatis</groupId>
	    <artifactId>mybatis-spring</artifactId>
	    <version>1.3.1</version>
	</dependency>

-classpath:config폴더 밑에 mybatis-config.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">
<configuration>
</configuration>

-datasource.xml파일 내 추가

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">


	<context:property-placeholder location="classpath:config/database.properties"/>
	
	<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
		<property name="driverClass" value="${db.driverClass}" />
		<property name="url" value="${db.url}" />
		<property name="username" value="${db.username}" />
		<property name="password" value="${db.password}" />
	</bean>
	
	<!-- sqlSessionFactory생성 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="configLocation" value="classpath:config/mybatis-config.xml"/>
		<property name="mapperLocations" value="classpath:mappers/*.xml" />
	</bean>
	
	<!-- sqlSessionFactory을 기반으로 sqlSession생성 -->
	<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg ref="sqlSessionFactory"/>
	</bean>

</beans>

-classpath:mappers폴더 생성 후 article-mapper.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="mappers.article-mapper"></mapper>

[Mapper XML 파일]

  • SQL문을 저장하는 존재
  • SQL에 집중할 수 있도록 만들어져 있다.
  • 반드시 DTD를 사용해서 작성해야 한다. 따라서 mybatis플러그인을 사용해서 작성하는 것을 권장

-작성 프로세스

0. DAO 클래스가 작성되면 이를 사용하는 SQL문 작성이 필요하다.

1. Mapper파일 위치 결정(classpath:mappers폴더 생성)

2. Mapper파일 작성하고 필요한 DTD 추가

3. SQL 작성

 

-CRUD

select, insert, update, delete

  • id는 무조건 필요
  • 쿼리 간 삽입OK ex ... select <include refid="userColumns"/>...
  • parameterType에는 Full Class명으로 적어줘야 한다. ex. kr.co.acomp....
  • 실제 Class와 다른 경우에는 ResultMap을 이용할 수 있다.

- MyBatis 로깅

  • Log4jdbc-log4j2 라이브러리 의존성 추가

 

Ex.mapper

-article-mapper.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="mappers.article-mapper">
	<!-- 실제 id는 namespace와 결합된다. -->
	<insert id="insertArticle" parameterType="kr.co.acomp.hello.vo.Article">
		insert into (article_id, author, title, content)
		values (#{articleId}, #{author}, #{title}, #{content})
	</insert>
	<select id="selectArticleById" resultType="kr.co.acomp.hello.vo.Article" parameterType="string">
		select 	article_id as articleId, 
				author, 
				title, 
				content 
		from 	article
		where	article_id = #{articleId}
	</select>
</mapper>

-ArticleDAO 수정

package kr.co.acomp.hello.dao;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import kr.co.acomp.hello.vo.Article;

@Repository
public class ArticleDAO {
	
	@Autowired
	SqlSession sqlSession;
	//sqlSession하나를 받는다.
	
	public void insertArticle(Article article) {
		sqlSession.insert(
				"mappers.article-mapper.insertArticle", article);
	}

	public Article selectArticleById(String articleId) {
		
		return sqlSession.selectOne(
				"mappers.article-mapper.selectArticleById", articleId);
	}
}

[Dynamic SQL: 동적 SQL]

  • if
  • trim(where, set) - 정상적인 쿼리를 위해서
  • choose(when, otherwise) - if~else문과 비슷
  • foreach - 반복문, 주로 IN과 함께 쓰인다.

Test가 중요

 

Ex. 동적 SQL

-ArticleDAOTest

package kr.co.acomp.hello.dao;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import kr.co.acomp.hello.vo.Article;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/servlet-context.xml")
@WebAppConfiguration
public class ArticleDAOTest {
	
	@Autowired
	private ArticleDAO dao;
	
	@Test
	@Ignore
	public void testInsertArticle() {
		Article article = new Article(2, "lee", "test", "test입니다.");
		dao.insertArticle(article);
	}
	
	@Test
	public void testSelectArticleById() {
		Article article = dao.selectArticleById("2");
		System.out.println(article);
		
		Assert.assertTrue(article.getAuthor().equals("lee"));
	}
	
}

테스트 성공