Backend/Spring

[Spring] MyBatis와 MyBatis-Spring 적용

땅지원 2022. 10. 21. 11:12
 

MyBatis – 마이바티스 3 | 시작하기

 

mybatis.org

 

mybatis-spring –

매퍼 주입 SqlSessionDaoSupport 나 SqlSessionTemplate 를 직접적으로 사용하는 데이터 접근 객체(DAO)를 생성하기 보다, 마이바티스 스프링 연동모듈은 다른 빈에 직접 주입할 수 있는 쓰레드에 안전한 매

mybatis.org

mapper 폴더를 만들고 db관련된 정보들을 저장한다(종종 book.xml, user.xml은 model package와 같이 둔다)

 

 

체크된 부분을 mybatis-config.xml에 저장해서 관리를 초기 환경 설정을 해준다.

 

그리고 어떤 DB를 불러들일껀지 읽어야하는데

<properties resource="mapper/dbinfo.properties"/>

dbinfo.properties라는 파일을 만들어서

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssafytest?serverTimezone=UTC&useUniCode=yes&characterEncoding=UTF-8
dbid=ssafy
dbpwd=023023

관련 정보를 저장해준다.

 

그리고 SqlMapConfig.java에 DB 관련 xml을 연동시켜주는 구문을 만들면

더보기
package com.ssafy.util;

import java.io.IOException;
import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class SqlMapConfig {
	
	private static SqlSessionFactory factory;

	static {
		try {
			String resource = "mapper/mybatis-config.xml";
			Reader reader = Resources.getResourceAsReader(resource);
			factory = new SqlSessionFactoryBuilder().build(reader);
		} catch (IOException e) {
			System.out.println("mybatis config parsing error");
			e.printStackTrace();
		}
	}

	public static SqlSession getSqlSession() {
		return factory.openSession();
	}
	
}

각 DaoImpl.java에 아래와 같이 사용할 수 있게 된다

SqlSession session = SqlMapConfig.getSqlSession();

int row = session.insert(NAMESPACE+".insert", book);
session.commit();

 

그리고 이제 각 model에서 사용되는 부분을 매핑구문으로 만들어야하는데 

 

MyBatis – 마이바티스 3 | 매퍼 XML 파일

Mapper XML 파일 마이바티스의 가장 큰 장점은 매핑구문이다. 이건 간혹 마법을 부리는 것처럼 보일 수 있다. SQL Map XML 파일은 상대적으로 간단하다. 더군다나 동일한 기능의 JDBC 코드와 비교하면

mybatis.org

여기서 Book이라는 객체를 과연 이 파일이 어떻게 알까?

<insert id="insert" parameterType="Book">
INSERT INTO BOOK(isbn, title, author, price, `desc`)
VALUES (#{isbn},#{title},#{author},#{price},#{desc})
</insert>

원래는 저렇게 Book이라는 객체 패키지를 써줘야하지만 이것도 반복되는 작업이기 때문에 "mybatis-config.xml"에서 설정을 해주면 된다!

<insert id="insert" parameterType="com.ssafy.book.model">
INSERT INTO BOOK(isbn, title, author, price, `desc`)
VALUES (#{isbn},#{title},#{author},#{price},#{desc})
</insert>
<typeAliases>
    <typeAlias type="com.ssafy.book.model" alias="Book" />
    <typeAlias type="com.ssafy.user.model" alias="User" />
</typeAliases>

 

최종적으로 paramaterTyte, resultType을 설정해준 형태가 아래와 같이 된다.

  <select id="selectByIsbn" parameterType="string" resultType="Book">
  SELECT isbn, title, author, price, `desc` FROM book WHERE isbn=#{isbn}
  </select>

 

아래와 같이 Connection, PreparedStatement를 사용하던 코드들을 확 줄일 수 있다.

더보기
	@Override
	public int insert(Book book) throws SQLException {
		SqlSession session = SqlMapConfig.getSqlSession();
		
		//return이 0,1로 나옴
		int row = session.insert(NAMESPACE+".insert", book);
		session.commit();
		return row;

//		Connection conn=null;
//		PreparedStatement stmt=null;
//		String sql="INSERT INTO Book(isbn, title, author, price, `desc`) VALUES (?,?,?,?,? )";
//
//		conn = db.getConncetion();
//		stmt = conn.prepareStatement(sql);
//		stmt.setString(1, book.getIsbn());
//		stmt.setString(2, book.getTitle());
//		stmt.setString(3, book.getAuthor());
//		stmt.setInt(4, book.getPrice());
//		stmt.setString(5, book.getDesc());
//		
//		int row = stmt.executeUpdate();
//  	
//		db.close(stmt, conn);
		
	}

 

	@Override
	public List<Book> select() throws SQLException {
		SqlSession session = SqlMapConfig.getSqlSession();
		List<Book> books = session.selectList(NAMESPACE+".select");
		
		return books;
		
//		Connection conn=null;
//		PreparedStatement stmt=null;
//        ResultSet result=null;
//		String sql="SELECT isbn, title, author, price, `desc` FROM book";
//		
//		List<Book> books = new ArrayList<Book>();
//		conn = db.getConncetion();
//		stmt = conn.prepareStatement(sql);
//		result = stmt.executeQuery();
//		while (result.next()) { 
//			books.add(new Book(
//							result.getString("isbn"),
//					 		result.getString("title"),
//					 		result.getString("author"),
//					 		result.getInt("price"),
//					 		result.getString("desc")
//					 		)
//					);   
//		}
//		return books;
	}

session.insert, session.selectList의 return형은 왜 int, List일까?

이 메소드는 SqlSession Class가 지정해준것이기 때문에 정해져있는걸 쓰는거고

NAMESPACE + ".xml정의한 id"로 하면 우리가 정의한 메소드가 불러와진다.

 

MyBatis 동적 SQL

	<sql id="search">
		<if test="word != null and word != ''">
			<if test="key == 'subject'">
				and subject like concat('%', #{word}, '%')
			</if>
			<if test="key != 'subject'">
				and ${key} = #{word}
			</if>
		</if>
	</sql>

	<select id="listArticle" parameterType="map" resultMap="article">
		select b.article_no, b.user_id, b.subject, b.content, b.hit, b.register_time, m.user_name
		from board b, members m 
		where b.user_id = m.user_id
		<include refid="search"></include>
		order by b.article_no desc
		limit #{start}, #{listsize}
	</select>
    
    <select id="getTotalArticleCount" parameterType="map" resultType="int">
		select count(article_no)
		from board
		<where>
			<include refid="search"></include>
		</where>
	</select>

하지만 이 모든것들은 Mybatis-Spring을 적용시키면 엄청 크게 압축할 수 있다.

 

root-context.xml에 mybatis-spring 관련 객체를 생성해주고 관리하게 한다

 

결국 Model dao에서 sql 관련된 모든 설정은 다 지우고 service에서 dao를 연결시켜줬으니까 service에서 model.xml를 불러와서 한번에 처리하게 한다.