본문 바로가기
mybatis

myBatis에 대하여

by Dodledd 2024. 4. 11.

myBatis란?

데이터 베이스를 쉽게 다룰 수 있게 도와주는 오픈소스 프레임워크이다.

 

여기서 프레임워크와 라이브러리의 차이를 알고가면 좋다.

 

둘 다 공통점은 개발을 편하게 도와준다는 것이다.

하지만 가장 큰 차이점이라고 하면 코드의 주도권이 바뀐다.

라이브러리는 우리가 추가적인 기능을 사용하여 코드를 주도적으로 작성하고 건드릴 수 있는 반면

프레임워크는 모든 과정이 정해져있어 우리가 설정만 해주면 알아서 코드가 튀어나가고 실행해서 값을 반환해준다.

우리가 손 쓸 틈이 없다는 것이다.(코드의 주도권이 우리에게 없다)

 

장점

  1. 성능 향상: 캐시 기능을 제공하여 데이터베이스 연산 속도가 높아진다.
  2. 간결성 : 쿼리와 프로그래밍 언어가 분리되어 유지보수가 좋아진다
  3. 유연성 : 동적 쿼리를 작성할 수 있다. (가장 큰 특징)

동적 쿼리란? 

우선 동적이란 우리가 java에서 쓰는 조건문, 반복문을 대표한다. 코드가 어떤 결과에 따라서 무엇을 실행할지 동적으로 바뀐다는 의미이다.

Mybatis에서는 동적쿼리 <if>, <choose>, <when>, <otherwise>, <foreach> 등 자바에서 유용하게 쓰이는 태그를 사용할 수 있다.

 

프레임 워크인만큼 세팅이 조금 많지만 세팅을 모두 해놓는다면 유지보수와 개발속도면에서 월등히 좋아지는 것이 좋다.

 

myBatis 설정

먼저 jar 파일을 받아야한다.

mybatis파일을 받고 라이브러리에 추가한다.

다이나믹프로젝트라면 lib폴더 안에 넣어놓는 것도 좋다. (추가는 해줘야함)

 

추가를 했다면 JDBC로 DB에 연결하기전에 xml 파일에 정보를 저장해줘야한다.

mybatis-config.xml파일

제일 밑 config파일을 작성해줘야한다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">
 <configuration>
 	<!-- settings : mybatis구동시 선언할 설정들을 작성하는 영역 -->
 	<settings>
 		<!-- 만약 null로 데이터가 전달되었다면 빈칸이 아닌 null로 인식해라(무조건 대문자 NULL) -->
 		<setting name="jdbcTypeForNull" value="NULL"/>
 	</settings>
 	<!-- typeAlias : VO/DTO 클래스들의 풀클래스명을 단순한 클래스명(별칭)으로 사용하기위한 별칭을 등록하는 영역-->
 	<typeAliases>
 		<typeAlias type="com.kh.mybatis.member.model.vo.Member" alias="Member" />
 		<typeAlias type="com.kh.mybatis.board.model.vo.Board" alias="Board" />
 	</typeAliases>
 	
 	<!-- environments : mybatis에서 연동할 DB정보들을 등록하는 영역-->
 	<environments default="development">
 		<environment id="development">
 			<!-- 
 				transactionManager : JDBC와 MANAGED 둘중 하나의 타입을 설정할 수 있다.
 				- JDBC : 트랜잭션을 내가 직접 관리할 것이다(수동commit)
 				- MANAGED : 트랜잭션에 대해서 어떠한 영향도 행사하지 않겠다.(자동commit) 
 			-->
 			<transactionManager type="JDBC"/>
 			<!-- 
 				*dataSource는 POOLED(사용)와 UNPOOLED(미사용) 둘중 하나의 타입을 선택할 수 있다.(connectionPool의 사용여부)
 				>> ConnectionPool : Connection객체를 담아둘 수 있는 영역
 									한번 생성된 Connection객체를 담아두면 재사용해서 쓸 수 있다.
 			 -->
 			<dataSource type="POOLED">
		        <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
		        <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
		        <property name="username" value="mybatis"/>
		        <property name="password" value="mybatis"/>
	        </dataSource>
 		</environment>
 	</environments>
 	<!-- mappers : 실행할 sql문들을 기록해둔 mapper파일들을 등록하는 영역 -->
 	<mappers>
 		<mapper resource="/mappers/member-mapper.xml"/>
 		<mapper resource="/mappers/board-mapper.xml"/>
 	</mappers>

 	
 </configuration>

 

이렇게 config 파일을 만들었다면 config.xml을 읽어들일 수 있게 만들어줘야한다.

이 과정을 template가 담당하게 되는데 별 다른건 없고 그냥 class파일 하나 만들어서 세팅해주면된다.

 

SqlSessionTemplate은 마이바티스 스프링 연동모듈의 핵심이다.

getMapper()에 의해 리턴된 매퍼가 가진 메서드를 포함해서 SQL을 처리하는 마이바티스 메서드를 호출할때 SqlSessionTemplate SqlSession이 현재의 스프링 트랜잭션에서 사용될수 있도록 보장한다. 추가적으로 SqlSessionTemplate은 필요한 시점에 세션을 닫고, 커밋하거나 롤백하는 것을 포함한 세션의 생명주기를 관리한다. 또한 마이바티스 예외를 스프링의 DataAccessException로 변환하는 작업또한 처리한다. -mybatis홈페이지.

package com.kh.mybatis.common.template;

import java.io.IOException;
import java.io.InputStream;

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 Template {
	//마이바티스
	public static SqlSession getSqlSession() {
		//mybatis-config.xml => 읽어드리기
		//해당 db와 접속된 SqlSession객체 생성해서 반환하기
		
		SqlSession sqlSession = null;
		
		//SqlSession생성하기 위해서는  => SqlSessionFactory객체 필요
		//SqlSessionFactory생성하기 위해서는 => SqlSessionFactoryBuilder필요
		
		String resource = "/mybatis-config.xml";
		
		try {
			InputStream inputStream = Resources.getResourceAsStream(resource);
//			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//			sqlSession = sqlSessionFactory.openSession(false); // boolean autoCommit => 자동커밋여부(true면 자동커밋 false면 수동커밋)
			
			sqlSession = new SqlSessionFactoryBuilder().build(inputStream).openSession(false);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return sqlSession;
	}

}

 

자 이제 우리는 하던대로 JDBC를 하다가 Dao에 도달했을 때 mybatis가 힘을내기시작한다.

본래라면 어떻게 해야하는가?

전달받은 객체에 conn에 이것을 저장할 PreparedStatement에 ResultSet에 쿼리까지 일일히 완성해줘야했었다.

매우 번거롭고 반복적인 작업이다. 하지만 이제 이 작업을 mybatis가 담당하게 된다.

 

그럼 간단하게 Member 하나를 insert한다고 해보자.

 

controller에서 하는 작업은 같다.

전달받은 값을 꺼내서 객체로 만들고 service로 보낸다.

 

service에서는 조금 달라진다

	public int insertMember(Member m) {
		SqlSession sqlSession = Template.getSqlSession();
		
		int result = mDao.insertMember(sqlSession, m);
		
		if (result > 0) {
			sqlSession.commit();
		} else {
			sqlSession.rollback();
		}
		
		sqlSession.close();
		
		return result;
	}

우리는 template에 sqlsession을 저장해놨고 이것으로 트랜젝션 처리를 해준다.

 

이제는 dao다.

public int insertMember(SqlSession sqlSession, Member m) {
    // insert문 => 처리된 행 수 => 트랜잭션처리	
    int result = sqlSession.insert("memberMapper.insertMember", m);
    return result;
}

그 많던 줄이 단 두줄로 요약됐다.

하지만 우리는 memberMapper.insertMember를 지정해줘야한다.

이것은 sql문을 담당하고 mapper파일에 고유한 별칭을 줌으로써 dao에서 찾아갈 수 있게 하고

sql문으로 DB에서 불러온 값을 우리가 만든 vo객체에 자동으로 저장할 경로를 맞춰주는 mapper역할이다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
  
<!-- namespace: 해당 mapper파일의 고유한 별칭 -->
<mapper namespace="memberMapper">
 <resultMap id="memberResultSet" type="Member">
 	<!--<result column="테이블 컬럼명" property="객체의 필드명" />-->
 	<result column="USER_NO" property="userNo" />
	<result column="USER_ID" property="userId" />
	<result column="USER_PWD" property="userPwd" />
	<result column="USER_NAME" property="userName" />
	<result column="EMAIL" property="email" />
	<result column="BIRTHDAY" property="birthday" />
	<result column="GENDER" property="gender" />
	<result column="PHONE" property="phone" />
	<result column="ADDRESS" property="address" />
	<result column="ENROLL_DATE" property="enrollDate" />
	<result column="MODIFY_DATE" property="modifyDate" />
	<result column="STATUS" property="status" />
 </resultMap>

 <!-- 
 	*DML문일 경우
 	<insert|update|delete id="식별자" [parameterType="전달받을 자바타입"] >
 
 	*SELECT문일 경우
 	<select id="각sql문의 식별자" [parameterType="전달받을 자바타입"] resultType="결과타입" | resultMap="결과객체">
 	</select>
  -->
  <insert id="insertMember" parameterType="Member">
  	INSERT 
  	INTO MEMBER
  	(
  		USER_NO,
		USER_ID,
		USER_PWD,
		USER_NAME,
		EMAIL,
		BIRTHDAY,
		GENDER,
		PHONE,
		ADDRESS
  	)
  	VALUES
  	(
  		SEQ_UNO.NEXTVAL,
  		#{userId},
  		#{userPwd},
  		#{userName},
  		#{email},
  		#{birthday},
  		#{gender},
  		#{phone},
  		#{address}
  	)
  </insert>
  </mapper>

여기까지했다면 끝이다.

 

dao는 db에서 가져온 값을 들고 service로 내려갔다가 controller로 반환될 것이다.

그럼 controller는 하던대로 프론트에 연결해주면 된다.

 

 

여기까지 간단하게 mybatis의 세팅에 대해 알아보았다.

두서가 없지만 사실 누구에게 알려주기 위한 글 이라기 보다는 나 자신에게 흐름을 정리해줄 필요가 느껴져서 작성한 글이다 ...

 

 

현재 세미프로젝트 진행중인데 mybatis를 적용시켜야겠다.

'mybatis' 카테고리의 다른 글

mybatis를 이용해서 페이징 처리  (0) 2024.04.14
mybatis로 페이징처리를 위한 공식  (0) 2024.04.13