Mybatis
1. 마이바티스(Mybatis)
- 마이바티스는 JDBC를 통해 구현했던 상당 부분의 코드와 파라미터 설정 및 결과 매핑을 xml 설정을 통해 쉽게 구현할 수 있게 해주는 영속성 프레임워크이다.
2. 마이바티스(Mybatis) 동작 구조
- mybatis-config.xml은 mybatis의 메인 환경 설정 파일이다.
- mapper.xml은 실행할 쿼리문과 매핑 구문을 정의해놓은 파일이다.
- SqlSession 객체는 실제 DB와 연결된 객체로 mapper.xml에 정의된 쿼리문을 실행시키고 실행 결과를 리턴 받는 객체이다.
3. mybatis-config
- mybatis-config.xml은 mybatis의 메인 환경 설정 파일이다.
<?xml version="1.0" encoding="UTF-8"?>
<!-- mybatis config 설정 파일임을 선언한다. -->
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 필요한 설정들을 작성한다. -->
</configuration>
- properties 요소는 외부 properties 파일의 내용을 불러올 때 사용하는 요소이다.
- properties 하위에 property 요소를 지정하여 mybatis-config.xml 사용할 값을 미리 지정할 수 있다.
<properties resource="driver.properties" />
또는
<properties>
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
<property name="user" value="KH"/>
<property name="password" value="KH"/>
</properties>
- properties 요소를 통해 불러온 값 또는 지정된 값을 아래와 같이 필요한 곳에서 사용할 수 있다.
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
- settings 요소는 mybatis 구동 시 선언할 설정들을 작성하는 요소이다.
<!-- 참고 : http://www.mybatis.org/mybatis-3/ko/configuration.html -->
<settings>
<setting name="jdbcTypeForNull" value="NULL"/>
</settings>
- typeAliases 요소는 mybatis에서 사용할 자료형의 별칭을 선언하는 요소이다.
<typeAliases>
<typeAlias type="cohttp://m.kh.mybatis.member.model.vo.Member" alias="Member"/>
<typeAlias type="cohttp://m.kh.mybatis.board.model.vo.Board" alias="Board"/>
</typeAliases>
Mybatis 내장 별칭
- environments 요소는 mybatis에서 연동할 DataBase 정보를 등록하는 요소이다.
<environments default="kh">
<environment id="kh">
<transactionManager type="JDBC"/>
<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="kh"/>
<property name="password" value="kh"/>
</dataSource>
</environment>
<!-- 여러 개의 DB를 등록하여 사용할 수 있다. -->
<environment id="web">
...
</environment>
</environments>
- transactionManager 요소의 타입
- JDBC는 JDBC가 commit과 rollback을 직접 사용 가능하게 하는 타입이다.
- MANAGED는 트랜잭션에 대해 어떠한 직접적인 영향도 행사하지 않는 타입이다.
dataSource 요소의 타입
구분 | POOLED | UNPOOLED |
특징 | 최초 Connection 객체를 생성할 때 여러 개의 Connection 객체 풀 영역에 저장해둔다. Connection 객체를 생성할 때 이를 재 사용한다. |
Connection 객체를 별도로 저장하지 않는다. 객체 호출 시 매번 생성하여 사용한다. |
장점 | Connection 객체를 생성하여 DataBase와 연결하는데 걸리는 시간이 단축된다. | Connection 연결이 많지 않은 코드를 작성할 때 간단하게 구현할 수 있다. |
단점 | 단순한 로직을 수행하는 객체를 만들기에는 설정해야 하는 정보가 많다. | 매번 새로운 Connection 객체를 생성하므로 속도가 상대적으로 느리다. |
- mappers 요소는 쿼리문과 데이터 매핑이 정의된 mapper 파일을 등록하는 요소이다.
<mappers>
<mapper resource="mappers/member/member-mapper.xml"/>
<mapper resource="mappers/board/board-mapper.xml"/>
</mappers>
4. mapper
- mapper.xml은 실행할 쿼리문과 매핑 구문을 정의해놓은 파일이다.
<?xml version="1.0" encoding="UTF-8"?>
<!-- mybatis mapper 설정 파일임을 선언한다. -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="memberMapper">
<!-- 필요한 쿼리문과 매핑 구문들을 작성한다. -->
</mapper>
- select 요소는 SQL의 조회 구문을 작성할 때 사용되는 요소이다.
<!-- 구문의 이름은 selectPerson이고 int 타입의 파라미터를 가진다. 그리고 결과 데이터는 HashMap에 저장된다. -->
<select id="selectPerson" parameterType="int" resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>
- select 요소의 주요 속성
속성 | 내용 |
id | 구문을 찾기 위해 사용될 수 있는 네임스페이스 내 유일한 구분자 |
parameterType | 구문에 전달될 파라미터의 클래스 명(패키지 경로 포함)이나 별칭 |
resultType | 리턴되는 타입의 패키지 경로를 포함한 전체 클래스 명이나 별칭, collection인 경우 list, arraylist로 설정할 수 있다. |
resultMap | 사용할 resultMap의 id를 기술한다. |
flushCache | 이 값을 true로 설정하면 구문이 호출될 때마다 로컬, 2nd 레벨 캐시가 지워진다(flush). (기본 값 : false) |
useCache | 이 값을 true로 설정하면 구문의 결과가 2nd 레벨 캐시에 저장된다. (기본값 : true) |
timeout | 예외가 발생하기 전에 데이터베이스의 요청 결과를 기다리는 최대 시간을 설정한다. 드라이버에 따라 지원되지 않을 수 있다. |
statementType | STATEMENT, PREPARED 또는 CALLABLE 중 하나를 선택할 수 있다. Mybatis에게 Statement, PreparedStatement 또는 CallableStatement를 사용하게 한다. (기본 값 : PREPARED) |
- resultMap과 resultType은 둘 모두를 사용할 수 없으며, 둘 중 하나만 선언해야 된다.
- insert, update, delete 요소는 데이터를 변경하는 구문을 작성할 때 사용되는 요소이다.
<insert id="insertMember" parameterType="Member">
INSERT INTO MEMBER
VALUES (
#{id},
#{name},
#{password},
#{email}
)
</insert>
<update id="updateMember" parameterType="Member">
UPDATE MEMBER
SET
NAME = #{name},
PASSWORD = #{password},
EMAIL = #{email},
WHERE ID = #{id}
</update>
<delete id="deleteMember" parameterType="int">
DELETE FROM MEMBER WHERE NO = #{no}
</delete>
- insert, update, delete 요소의 주요 속성
속성 | 내용 |
id | 구문을 찾기 위해 사용될 수 있는 네임스페이스 내 유일한 구분자 |
parameterType | 구문에 전달될 파라미터의 클래스 명(패키지 경로 포함)이나 별칭 |
flushCache | 이 값을 true로 설정하면 구문이 호출될 때마다 캐시가 지워진다(flush). (기본값 : false) |
timeout | 예외가 발생하기 전에 데이터베이스의 요청 결과를 기다리는 최대 시간을 설정한다. 드라이버에 따라 지원되지 않을 수 있다. |
userGeneratedKeys | insert, update에만 적용되는 속성이다. 데이터베이스에서 내부적으로 생성한 키를 받는 JDBC getGeneratedKeys 메소드를 사용하도록 설정한다. (기본 값 : false) |
keyProperty | insert, update에만 적용되는 속성이다. getGeneratedKeys 메소드나 insert 구문의 selectKey 태그의 결과가 세팅될 대상 프로퍼티 설정이다. 여러 개의 컬럼을 사용한다면 프로퍼티 명에 콤마를 구분자로 나열할 수 있다. |
- resultMap 요소는 쿼리문의 조회한 결과를 객체와 매핑하기 위한 요소이다.
<!-- type 속성은 실제로 구현해 놓은 자바 클래스를 지정한다. -->
<resultMap type="Member" id="memberResultMap">
<id property="no" column="NO"/>
<result property="id" column="ID" />
<result property="password" column="PASSWORD"/>
<result property="email" column="EMAIL"/>
</resultMap>
5. SqlSession 객체
5.1. SqlSessionFactoryBuilder 객체
- mybatis-config.xml을 읽어들여 SqlSessionFactory 객체를 생성한다.
메소드 | 설명 |
build(InputStream) | config.xml 파일만 불러옴 |
build(InputStream, String) | config.xml 파일과 지정한 DB를 불러옴 |
build(InputStream, Properties) | config.xml 파일과 프로퍼티로 설정한 내용으로 불러옴 (“${key명 }”) |
build(InputStream, String, Properties) | config.xml 파일과 지정한 DB,Properties 파일을 불러옴 |
build(configuration) | configuration 객체에 설정한 내용을 불러옴 |
5.2. SqlSessionFactory 객체
- SqlSession 객체는 SqlSessionFactory 객체를 통해 생성한다
메소드 | 설명 |
openSession() | 기본 값을 통해 SqlSession을 생성한다. |
openSession(Boolean) | SqlSession 생성 시 AutoCommit 여부를 true / false로 지정할 수 있다. (기본 값 : true) |
openSession(Connection) | 직접 생성한 Connection 객체를 이용해 SqlSession을 생성한다. (기본 값 :X) |
openSession(ExecutorType) | 쿼리를 실행할 때 PreparedStatement의 재사용 여부를 설정한다. (기본 값: ExecutorType.SIMPLE) |
5.3. SqlSession 객체
- SqlSession 객체를 통해 mapper에 정의된 쿼리를 실행할 수 있다.
- SqlSession 객체는 쿼리문을 실행하기 위한 다양한 메소드를 가지고 있다.
session.selectOne("namespace.query_id");
- SqlSession 메소드
메소드 | 반환형 | 설명 |
selectOne(String mapper, Object param) | Object | 하나의 객체만을 받고자 할 때 사용 |
selectList(String mapper, Object param) | List<E> | 결과에 대한 값을 List로 받고자 할 때 사용 |
selectMap(String mapper, Object param, String mapKey) |
Map<K, V> | 결과에 대한 값을 Map으로 받고자 할 때 사용 (마지막 인자로 키로 사용될 컬럼을 명시) |
insert(String mapper, Object param) | int | DB에 데이터를 입력하고자 할 때 사용 |
update(String mapper, Object param) | int | DB에 데이터를 입력하고자 할 때 사용 |
delete(String mapper, Object param) | int | DB에 데이터를 입력하고자 할 때 사용 |
마이바티스 동적 쿼리
1. 동적 쿼리(SQL)
- 동적 쿼리는 마이바티스의 강력한 기능 중 하나이다.
- 마이바티스에서는 쿼리를 동적으로 제어할 수 있는 요소(Element)들을 제공한다.
동적 쿼리 요소들을 사용하여 좀 더 쉽게 쿼리를 구현할 수 있다.
2. if 요소
- 자바의 if 구문과 같은 역할을 하는 요소이다.
- 특정 조건을 만족할 경우 요소 안의 구문을 쿼리에 포함시키는 요소이다.
<select>
SELECT *
FROM BOARD
WHERE STATUS = 'Y'
<if test="writer != null">
AND WRITER = #{writer}
</if>
</select>
- 필요로 하는 조건이 1개 이상일 경우 if 요소를 여러 개 사용할 수 있다.
<select>
SELECT *
FROM BOARD
WHERE STATUS = 'Y'
<if test="writer != null">
AND WRITER = #{writer}
</if>
<if test="title != null">
AND TITLE = #{title}
</if>
</select>
3. choose 요소
- 자바의 switch 구문과 같은 역할을 하는 요소이다.
- 하위 요소인 when, otherwise 요소와 함께 사용한다.
<select>
SELECT *
FROM BOARD
WHERE STATUS = 'Y'
<choose>
<when test="writer != null">
AND WRITER = #{writer}
</when>
<when test="title != null">
AND TITLE = #{title}
</when>
<otherwise>
<!-- 위의 조건 중 하나도 만족하지 않는 경우 -->
</otherwise>
</choose>
</select>
4. foreach 요소
- 자바의 for 구문에 해당하는 역할을 하는 요소로 배열과 컬렉션에 대한 반복 처리에 사용된다.
<select>
SELECT COUNT(*)
FROM BOARD
WHERE STATUS = 'Y'
AND TITLE IN
<foreach item="item" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
- foreach 요소의 속성
속성 | 설명 |
item | 반복될 때 접근 가능한 각 객체 변수 |
index | 반복되는 횟수를 가리키는 변수, 0부터 순차적으로 증가 |
collection | 전달받은 인자로 반복에 쓰이는 Collection 객체(List나 Array만 가능) |
open | 해당 구문이 시작될 때 삽입할 문자열 |
separator | 반복되는 객체를 나열할 때 사용할 구분자 |
close | 해당 구문이 종료될 때 삽입할 문자열 |
5. trim, where, set, bind 요소
- 동적 쿼리의 잘못된 사용 예시이다.
<select>
SELECT *
FROM BOARD
WHERE
<if test="writer != null">
WRITER = #{writer}
</if>
<if test="title != null">
AND TITLE = #{title}
</if>
</select>
- if 요소의 조건들을 모두 만족하지 못했을 경우에는 아래와 같은 쿼리가 만들어진다.
SELECT * FROM BOARD
WHERE
두 번째 if 요소의 조건만 만족했을 경우에는 아래와 같은 쿼리가 만들어진다.
SELECT * FROM BOARD
WHERE AND TITLE = 'OOO'
5.1. where 요소
- 쿼리문의 WHERE 절을 동적으로 구현할 때 사용하는 요소이다.
- 단순히 WHERE만을 추가하지만, 요소 안의 내용이 'AND'나 'OR'로 시작할 경우 'AND'나 'OR'를 제거한다.
<select>
SELECT *
FROM BOARD
<where>
<if test="writer != null">
WRITER = #{writer}
</if>
<if test="title != null">
AND TITLE = #{title}
</if>
</where>
</select>
5.2. set 요소
- UPDATE 쿼리문의 SET 절을 동적으로 구현할 때 사용하는 요소이다.
- UPDATE 하고자 하는 컬럼을 동적으로 포함시키기 위해 사용한다.
- set 요소는 SET 키워드를 붙이고 불필요한 콤마를 제거한다.
<update>
UPDATE MEMBER
<set>
<if test="name != null">
NAME = #{name},
</if>
<if test="address != null">
ADDRESS = #{address}
</if>
</set>
</update>
5.3. trim 요소
- 쿼리문의 특정 구문을 추가하거나 없앨 때 사용하는 요소이다.
- 요소 안의 쿼리문이 완성될 때 처음 시작할 단어(prefix)와 시작 시 제거해야 할 단어(prefixOverrides)를 명시하여 where 요소와 동일한 기능을 하도록 구현할 수 있다.
<select>
SELECT *
FROM BOARD
<trim prefix="WHERE" prefixOverrides="AND|OR">
<if test="writer != null">
WRITER = #{writer}
</if>
<if test="title != null">
AND TITLE = #{title}
</if>
</trim>
</select>
- 요소 안의 쿼리문이 완성될 때 처음 시작할 단어(prefix)와 마지막에 제거해야 할 단어(suffixOverrides)를 명시하여 set 요소와 동일한 기능을 하도록 구현할 수 있다.
<update>
UPDATE MEMBER
<trim prefix="SET" suffixOverrides=",">
<if test="name != null">
NAME = #{name},
</if>
<if test="address != null">
ADDRESS = #{address}
</if>
</trim>
</update>
5.4. bind 요소
- 특정 문장을 미리 생성하여 변수를 만든 뒤 쿼리에 적용할 때 사용한다.
_parameter를 통해 전달받은 값에 접근하여 구문을 생성할 수 있다.
<select>
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>