본문 바로가기
Spring

스프링에서 마이바티스(Mybatis) 사용하기

qbang 2021. 10. 13.
 

마이바티스(MyBatis)

마이바티스 개념 The MyBatis Blog A blog about the the MyBatis data mapper framework. blog.mybatis.org 마이바티스는 자바 퍼시스턴스 프레임워크의 하나로 XML 서술자나 어노테이션을 사용하여 저장 프로시..

bangsj1224.tistory.com

마이바티스는 XML 서술자나 어노테이션을 사용하여 저장 프로시저나 SQL 문으로 객체들을 연결해주는 프레임워크이다. 들어가기 앞서 마이바티스에 대한 자세한 내용은 위 포스팅을 참고하자.

 

종속성 추가

<dependencies>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.6</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.5</version>
    </dependency>
    ...
</dependencies>

스프링에서 Mybatis를 사용하기 위해서는 pom.xml에 설정을 추가해준다. 최신 버전은 https://mvnrepository.com/에서 찾을 수 있다. 

 

root-context.xml

모든 마이바티스 애플리케이션은 SqlSessionFactory 인스턴스를 사용한다. SqlSessionFactory 인스턴스는 SqlSessionBuilder를 사용하여 만들 수 있다. SqlSessionFactoryBuilder는 XML 설정 파일에서 SqlSessionFactory 인스턴스를 빌드할 수 있다.

<?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"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
		http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
	
	<!-- A구역 -->
	<bean id="dataSourceSpied"
		class="org.apache.commons.dbcp2.BasicDataSource">
		<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://주소:포트/DB이름?characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
		<property name="username" value="아이디"/>
		<property name="password" value="비밀번호"/>
	</bean>
	<bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource"> 
	    <constructor-arg ref="dataSourceSpied" /> 
	    <property name="logFormatter"> 
	        <bean class="net.sf.log4jdbc.tools.Log4JdbcCustomFormatter"> 
	            <property name="loggingType" value="MULTI_LINE" /> 
	            <property name="sqlPrefix" value="SQL : "/> 
	        </bean> 
	    </property> 
	</bean>
	
	<!-- B구역 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="classpath:/mybatis/mybatisConfig.xml" />
		<property name="mapperLocations" value="classpath:/mybatis/mybatisMapper.xml" />
	</bean>
	
	<!-- C구역 -->
	<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
	</bean>
</beans>

XML 설정 파일에서는  데이터베이스 Connection 인스턴스를 가져오기 위한 DataSource를 포함한다. 글쓴이는 수행되는 쿼리를 확인하기 위해서 Log4jdbcProxyDataSource를 사용하였다. A구역에서는 드라이버 클래스 이름, 연결 URL, 유저 이름 및 비밀번호를 프로퍼티로 사용하여 Connection을 만든다. B구역에서는 1번에서 만든 Connection과 설정을 프로퍼티로 사용하여 sqlSessionFactory를 생성한다. C구역에서는 마이바티스의 핵심 템플릿을 담아놓은 라이브러리를 sqlSessionFactory에 적용하여 sqlSession 객체를 만든다.

 

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> 
	<typeAliases>
		<typeAlias alias="MemberVO" type="패키지명.MemberVO"/>
		<typeAlias alias="DateParam" type="패키지명.DateParam"/>
		<typeAlias alias="DateVO" type="패키지명.DateVO"/>
		<typeAlias alias="FeelingVO" type="패키지명.FeelingVO"/>
		<typeAlias alias="DetailParam" type="패키지명.DetailParam"/>
	</typeAliases>
</configuration>

직접 정의한 VO 객체로 결과를 받아오기 위해 자주 사용하는 타입의 별칭을 작성해준다. typeAlias 태그의 alias 속성에는 alias로 지정할 클래스 명을 적고, type 속성에는 클래스의 패키지 주소를 적는다.

 

mybatis-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="mogi">
	<select id="selectUser" parameterType="string" resultType="MemberVO">
		select * from user where userId=#{value}
	</select>
	<insert id="insertUser" useGeneratedKeys="true" keyProperty="id" parameterType="MemberVO">
		insert into user(userId, userPw) values(#{userId},#{userPw})
	</insert>
	...
</mapper>

 

이제 DAO안의 SqlSession은 해당 Mapper 파일을 참고하여 쿼리를 수행한다. mapper 하위 엘리먼트의 종류는 다음과 같다.

  • cache: 해당 네임스페이스를 위한 캐시 설정
  • cache-ref: 다른 네임스페이스의 캐시 설정에 대한 참조
  • resultMap: 결과데이터를 객체에 로드하는 방법을 정의
  • parameterMap: 파라미터를 매핑하기 위해 사용되었으나 현재는 권장하지 않음
  • sql: 다른 구문에서 재사용하기 위한 SQL 조각
  • insert: 매핑된 insert 구문
  • update: 매핑된 update 구문
  • delete: 매핑된 delete 구문
  • selefct: 매핑된 select 구문

 

select

<?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="mogi">
	<select id="selectUser" parameterType="string" resultType="MemberVO">
		select * from user where userId=#{value}
	</select>
	...
</mapper>

데이터베이스에서 데이터를 가져오는 엘리먼트이다. 동일한 유형을 제거하고 보자. parameterType과 resultType은 이름에서 알 수 있듯이 각각 파라미터로 넣을 값의 타입, 결과로 받을 값의 타입을 의미한다.

public class MemberVO {

	private int id;
	private String userId;
	private String userPw;
	
	public String getUserId() {
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getUserPw() {
		return userPw;
	}
	public void setUserPw(String userPw) {
		this.userPw = userPw;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
}

위 쿼리는 string 타입 value 파라미터와 userId가 일치하는 행을 가져와서 MemberVO에 세팅(setter)한 후 해당 MemberVO를 돌려준다.

 

insert, update, delete

insert, update, delete는 동일한 엘리먼트 속성을 가진다. 

  • parameterType: 구문에 전달될 파라미터의 패키지 경로를 포함한 전체클래스명이나 별칭이다.
  • parameterMap: 외부 parameterMap을 찾기 위한 접근 방법. 비권장
  • flushCache: true이면 구문이 호출될 때마다 캐시가 지워진다. 디폴트는 false 이다.
  • timeout: 예외가 발생하기 전에 요청 결과를 기다리는 최대 시간을 설정한다.
  • statementType: STATEMENT, PREPARED, CALLABLE 중 하나를 선택할 수 있다. 디폴트는 PREPARED이다.
  • useGenerateKeys: 데이터베이스에서 내부적으로 생성한 키(ex. 자동 증가 필드)를 이용하는 테이블에서 사용(insert, update 엘리먼트에서만 사용 가능)
  • keyProperty: getGenerateKeys 메서드나 insert 엘리먼트의 selectKey 속성에 의해 리턴된 키를 세팅할 프로퍼티를 지정(insert, update 엘리먼트에서만 사용 가능)
  • keyColumn: 생성키를 가진 테이블의 컬럼명을 세팅. 키 컬럼이 첫 번째 컬럼이 아닌 DB(ex. PostgreSQL)에서만 필요(insert, update 엘리먼트에서만 사용 가능)
  • databaseId: 설정된 databaseIdProvider가 있는 경우 databaseId 속성이 없는 모든 구문을 로드하거나 일치하는 모든 databaseId와 함께 로드될 것이다. 만약 databaseId가 여러 개 나오는 경우 첫번째 것을 제외하고 무시한다.

 

statementType에 대한 추가 설명

  • PREPARED는 DBMS에서 동일하거나 비슷한 쿼리를 높은 효율성으로 반복 실행하기 위해 사용되는 기능이다. 애플리케이션에서는 쿼리 틀만 만들고 DBMS가 이를 받아 쿼리를 컴파일하여 그 결과만 저장한다. 이후 애플리케이션이 변수에 값을 바인드하면 DBMS는 쿼리문을 실행한다.
  • STATEMENT는 쿼리를 수행할 때마다 매번 PREPARED의 단계들을 수행한다. 즉, PREPARED는 캐시를 사용하지만 STATEMENT는 캐시를 사용하지 않아 반복적으로 동일한 쿼리를 사용한다면 PREPARED가 효과적이다.
  • CALLABLE은 프로시저나 함수를 호출하기 위하여 사용한다.

 

insert

<?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="mogi">
	<insert id="insertUser" useGeneratedKeys="true" keyProperty="id" parameterType="MemberVO">
		insert into user(userId, userPw) values(#{userId},#{userPw})
	</insert>
	...
</mapper>

user 테이블의 PK는 auto_increment이기 때문에 useGenerateKeys를 사용하였다. 이 경우 자동 생성키는 keyProperty로 컬럼 이름을 명시하고 쿼리에서는 컬럼 이름이나 값을 명시해주지 않아도 된다.

 

update

<update id="updateAuthor" parameterType="domain.blog.Author" flushCache="true" 
	statementType="PREPARED" timeout="20">

 

delete

<delete id="deleteAuthor">
  delete from Author where id = #{id}
</delete>

 

참고

 

댓글