데이터의 입력, 조회, 수정, 삭제(CRUD)를 보다 편하게 하기 위해 xml로 구조화한 Mapper 설정 파일을 통해 JDBC를 구현한 영속성 프레임워크 기존 JDBC를 통해 구현했던 상당 부분의 코드와 파라미터 설정 및 결과 매핑을 xml 설정을 통해 쉽게 구현할 수 있게 함
ORM 기술 중 하나로 대체 기술로는 JPA가 존재하나 여전히 국내에선 MyBatis도 많이 활용됨
MyBatis API Site: https://mybatis.org/mybatis-3/ko/
| 구분 | MyBatis | JPA |
|---|---|---|
| 개념 | JDBC Driver 기반으로 Java 코드와 SQL을 분리하고, 반자동 매핑 기능을 제공하는 SQL Mapper 프레임워크 | 객체(Object)와 테이블(Table)을 1:1로 매핑하고, DDL·DML을 자동 생성하는 ORM 표준 |
| 특징 | DB 종속적 SQL 분리 관리 부분 자동 매핑 지원 동적 SQL 작성에 강점 | DB 독립성 SQL 자동 생성 객체-테이블 자동 매핑 다중 DB 지원 |
| DB 관리 방식 | DB별 SQL을 XML로 관리 필요에 따라 Mapper XML을 추가 | 엔티티 매핑 기반 자동 관리 별도 DB별 설정 불필요 |
| 구현 방식 | XML 기반 SQL과 코드 1:1 관리 Mapper 인터페이스를 통해 호출 | 엔티티에 어노테이션으로 매핑JpaRepository 상속 시 CRUD 자동 제공필요한 기능만 추가 구현 |
| 동적 쿼리 | MyBatis 전용 문법(<if>, <foreach> 등)으로 강력한 동적 쿼리 지원 | 자체적인 동적 쿼리 기능은 제한적 Criteria API, QueryDSL 등 라이브러리 활용 필요 |
| 장점 | 복잡한 쿼리·동적 쿼리 작성에 탁월 쿼리 튜닝 및 캐시 전략으로 성능 최적화 용이 | DDL·DML 자동 생성으로 생산성 향상 DB 독립적이라 코드 재사용성 높음 |
| 단점 | 생산성 저하 가능 DB 종속적이어서 DB별 Mapper 관리 부담 | 자동 생성 쿼리의 성능 이슈 가능 (튜닝 필요) 복잡한 쿼리 표현에 한계 |
| 활용 사례 | DB 종속 환경에서 복잡한 쿼리·고성능 튜닝이 중요한 경우 (SI, 금융권, 레거시 프로젝트 등) | DB 독립적인 제품·솔루션 개발 개발 생산성이 중요한 환경 (스타트업, 최근 일반적인 Spring Boot 프로젝트) |
이전 JDBC Template을 통해 SQL을 실행하였다면 MyBatis의 구조를 통하여 접근 가능 (실제 사용자는 JDBC를 구현하지 않음)


Apache에서 ibatis의 개발 팀이 2010년 5월 9일에 Google팀으로 이동하면서 MyBatis로 이름을 변경
MyBatis는 기존 ibatis의 한계점이었던 동적 쿼리와 어노테이션 처리를 보강하여 더 나은 기능 제공
ibatis는 현재 비활성화 상태이며 기존에 ibatis로 만들어진 애플리케이션의 지원을 위해 라이브러리만 제공하고 있으며, 신규 사용은 MyBatis를 권장
| ibatis | MyBatis | |
|---|---|---|
| Java 요구 버전 | JDK 1.4 이상 | JDK 1.5이상 |
| 패키지 구조 com.ibatis.* | org.apache.ibatis.* | |
| 사용 용어 | SqlMapConfig sqlMap resultClass | Configuration Mapper resultType |
| 동적쿼리/어노테이션 | X | O |
MyBatis 초기 버전에서는 기본형에 대하여 ‘_’ 규칙을 통해 java 호환성 확보를 하였지만, 1.5 버전 이후 부터는 autoboxing이 지원되면서 지키지 않아도 문제 없음
| MyBatis 타입(alias) | Java 자료형 |
|---|---|
_byte | byte |
byte | Byte |
_short | short |
short | Short |
_int, _integer | int |
int, integer | Integer |
_long | long |
long | Long |
_float | float |
float | Float |
_double | double |
double | Double |
_boolean | boolean |
boolean | Boolean |
string | String |
date | Date |
object | Object |
map | Map |
hashmap | HashMap |
list | List |
arraylist | ArrayList |
collection | Collection |
iterator | Iterator |
| 구분 | POOLED | UNPOOLED |
|---|---|---|
| 특징 | 최초 Connection 객체를 생성할 때 해당 정보를 pool 영역에 저장해두고 이후 Connection 객체를 생성할 때 이를 재사용함 | Connection 객체를 별도로 저장하지 않고 객체 호출 시 매번 생성하여 사용 |
| 장점 | Connection 객체를 생성하여 DataBase와 연결을 구축하는데 걸리는 시간이 단축 됨 | Connection 연결이 많지 않은 코드를 작성할 때 간단하게 구현 가능 |
| 단점 | 단순한 로직을 수행하는 객체를 만들기에는 설정해야 할 정보가 많음 | 매번 새로운 Connection 객체를 생성하므로 속도가 상대적으로 느림 |
‘resources’ 폴더 안에 ‘mappers’폴더 생성 후 그 안에 식별하기 쉬운 이름을 지어 파일 등록
xml 최상단에 아래와 같이 xml형식을 지정하여 이하의 설정 내용이 MyBatis mapper 설정임을 선언
<?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 속성 기입, 이후 작성될 태그들은 <mapper>태그 안에 기록
<mapper namespace="memberMapper">
<!-- mapper 내부에 작성될 내용 -->
</mapper>
<resultMap> 태그: 조회한 결과를 객체와 Row간의 1:1 매칭이 아닌 원하는 객체의 필드에 담아 반환하고자할 때 사용
<resultMap Type="Member" id="memberResultSet">
<!-- property = 자바의 필드 변수 이름 / column = DB의 해당 컬럼 -->
<!-- id는 primary key / result는 일반 컬럼 -->
<id property="mid" column="MID"/>
<result property="userId" column="USER_ID"/>
<result property="userPwd" column="USER_PWD"/>
<result property="userName" column="USER_NAME"/>
</resultMap>
<resultMap>의 type 속성은 실제로 구현해 놓은 자바 POJO객체를 사용해야 하며, mybatis-config.xml에서 typeAlias를 지정하지 않은 경우 패키지 명부터 클래스 명까지 모두 기술해야 함
<select> 태그 : SQL의 조회구문을 작성 할 때 사용되는 태그, 해당 쿼리를
외부에서 접근하고자 할 때 namespace.id명을 적어 접근 가능
<select id="memberInfo" parameterType="string" resultType="_int">
<!-- #{field}는 pstmt의 '?'의 역할이며, 전달된 값을 뜻함
또한 여러 줄로 줄 바꿈 문자를 섞어 사용도 가능하다.
단, 쿼리의 마지막을 알리는 세미콜론은 에러를 유발한다. -->
SELECT *
FROM MEMBER
WHERE USER_ID = #{userId}
</select>
| 속성 명 | 내용 |
|---|---|
| id | 구문을 찾기 위해 사용될 수 있는 네임스페이스 내 유일한 구분자 |
| parameterType | 구문에 전달될 파라미터의 클래스 명(패키지 경로 포함)이나 별칭 |
| resultType | 리턴되는 타입의 패키지 경로를 포함한 전체 클래스 명이나 별칭, collection인 경우 list, arraylist로 설정 가능 |
| resultMap | 리턴되는 타입의 필드 명이 다를 때 사용하며 직접 이름을 지정하여 매칭 |
resultMap과 resultType은 둘 모두를 사용할 수 없으며 둘 중 하나만 선언해야 함
| 속성 명 | 내용 |
|---|---|
| flushCache | 기본 값은 false이며 이 값을 true로 설정하면 구문이 호출 될 때마다 로컬, Second Level 캐시가 초기화 된다. |
| useCache | 기본 값은 true이며 이 값을 true로 설정하면 구문의 결과가 Second Level 캐시에 저장 |
| timeout | 예외가 발생하기 전에 데이터베이스의 요청 결과를 기다리는 최대 시간 설정, 드라이버에 따라 다소 지원되지 않을 수 있음 |
| statementType | STATEMENT, PREPARED 또는 CALLABLE 중 하나 선택 가능(기본 값 : PREPARED) MyBatis에게 Statement, PreparedStatement, CallableStatement를 사용하게 함 |
MyBatis는 Cache(캐시) 기능 지원하여 최근에 요청한 쿼리와 결과를 저장하고 중복된 쿼리를 요청하면 이를 대신 응답하는 구조로 구성되어 있다. (Commit 기준)
이러한 캐시는 Local Session Cache와 Second Level Cache 두가지로 구성되어 있다.
Local Sesion Cache는 무조건적으로 활성화 되며 SqlSession 객체에 Cache가 되며 Second Level Cache는 Mapper namespace 단위로 Cache가 되며 On/Off 설정이 가능하다.
<insert>, <update>, <delete> 태그 : 해당 태그들은 설정 동일
<insert id="insertMember" parameterType="Member" flushCache="true" statementType="PREPARED", useGeneratedKeys="true" timeout="20">
INSERT INTO MEMBER VALUES(
#{userId}, #{userPwd}, #{userName}
)
</insert>
| 속성 명 | 내용 |
|---|---|
| id | 구문을 식별하기 위한 값으로, 네임스페이스(namespace) 내에서 유일해야 합니다. |
| parameterType | SQL 구문에 전달될 파라미터의 클래스 타입을 지정합니다. (패키지 경로 포함 클래스명 또는 Type Alias 사용 가능) |
| flushCache | 기본값은 false입니다. true로 설정하면 해당 구문이 호출될 때마다 캐시가 초기화됩니다. |
| timeout | 예외가 발생하기 전까지 데이터베이스 요청 결과를 기다리는 최대 시간을 설정합니다. JDBC 드라이버에 따라 지원되지 않을 수 있습니다. |
| useGeneratedKeys (insert, update 전용) | DB에서 내부적으로 생성한 키(예: MySQL, SQL Server의 auto-increment)를 가져오기 위해 JDBC의 getGeneratedKeys() 메서드를 사용하도록 설정합니다. (기본값: false) |
| keyProperty (insert, update 전용) | getGeneratedKeys() 또는 <selectKey>의 실행 결과를 저장할 객체의 프로퍼티명을 지정합니다. 여러 컬럼을 사용할 경우 콤마(,)로 구분하여 나열합니다. |
mybatis-config.xml, *-mapper.xml 파일 생성을 완료했다면
common패키지를 만들어 싱글톤을 적용한 Template 클래스를 만들고 SqlSession을 반환해주는 static 메소드 작성

| 메서드 | 설명 |
|---|---|
build(InputStream) | config.xml 파일만 로드하여 SqlSessionFactory를 생성합니다. |
build(InputStream, String) | config.xml 파일과 지정한 DB(environment id) 설정을 함께 로드합니다. |
build(InputStream, Properties) | config.xml 파일과 Properties로 전달된 설정 값을 함께 로드합니다.${key} 형태로 XML 내에서 참조할 수 있습니다. |
build(InputStream, String, Properties) | config.xml 파일, 지정한 DB(environment id), Properties 설정 값을 모두 로드합니다. |
build(Configuration) | 이미 구성된 Configuration 객체에 설정된 내용을 기반으로 SqlSessionFactory를 생성합니다. |
| 메서드 | 설명 |
|---|---|
openSession() | 기본 설정값을 사용하여 SqlSession을 생성합니다. |
openSession(boolean autoCommit) | SqlSession 생성 시 AutoCommit 여부를 true / false로 지정합니다.(기본값: true) |
openSession(Connection connection) | 사용자가 직접 생성한 Connection 객체를 사용하여 SqlSession을 생성합니다.(기본값 없음) |
openSession(ExecutorType executorType) | 쿼리 실행 시 PreparedStatement 재사용 전략을 지정합니다.(기본값: ExecutorType.SIMPLE) |

| 메서드 | 반환형 | 설명 |
|---|---|---|
selectOne(String statement, Object parameter) | Object | 단일 결과 객체를 조회할 때 사용합니다. 조회 결과가 2건 이상이면 예외가 발생합니다. |
selectList(String statement, Object parameter) | List<E> | 조회 결과를 List 형태로 반환합니다. 다건 조회에 사용됩니다. |
selectMap(String statement, Object parameter, String mapKey) | Map<K, V> | 조회 결과를 Map 형태로 반환합니다. 마지막 인자로 Map의 Key로 사용할 컬럼명(또는 프로퍼티명)을 지정합니다. |
insert(String statement, Object parameter) | int | DB에 데이터를 삽입할 때 사용합니다. 반환값은 영향 받은 행(row) 수입니다. |
update(String statement, Object parameter) | int | DB의 데이터를 수정할 때 사용합니다. 반환값은 영향 받은 행(row) 수입니다. |
delete(String statement, Object parameter) | int | DB의 데이터를 삭제할 때 사용합니다. 반환값은 영향 받은 행(row) 수입니다. |
DB에서 쿼리는 정적인 성격으로 한번 완성된 쿼리는 일반적으로 재사용하거나 변형하기 어렵다.
웹에서는 경우에 따라 다양한 검색 옵션이 활성화 되는 경우가 있고, 이때 경우의 수에 따라 다수의 쿼리를 작성해야 하거나 통합된 쿼리로 만드는데, 어려움이 발생한다.
동적 SQL이란 다양한 경우의 수를 가지는 쿼리를 if문과 for문과 같은 제어문을 통해 다양한 경우의 수에도 동적으로 변경되는 쿼리를 작성하는 기술이다.
Mybatis에서는 파라미터 표현법으로 EL 표현법과 유사하게 활용한다.
#{param}의 경우 문자열과 숫자를 구분하여 문자의 경우 ‘(싱글쿼테이션)을 자동으로 추가한다.
ex) #{param} -> ‘param’, #{}은 쿼리에 보안적으로 안전하게 문자열을 주입됨으로 권장되는 표현
${param}의 경우 파라미터를 바로 주입되는 표현법이다. ex) ${param} -> param
${} 표현법의 경우 그대로 주입됨에 따라 SQL injection을 유의해 한다.

XML 고유 문법으로 XML 태그 내부에 XML 표현법으로 활용되는 특수문자를 표현할 때 활용된다.
주로 태그 표현(<b></b>)와 같은 표현법을 XML 내부 컨텐츠로 활용하기 위해 활용된다.
Mybatis의 경우 SQL 자체에 >,<를 대소 비교 시 활용됨에 따라 간혹 CDATA 구문이 활용된다.

동적 쿼리를 구현할 때 가장 기본적으로 사용되는 구문으로 특정 조건을 만족할 경우 안의 구문을 쿼리에 포함 시킴

필요로 하는 조건이 1개 이상일 시 if구문을 여러 개 사용 가능

자바의 if-else, switch, JSTL의 choose 구문과 유사하며 주어진 구문 중 한 가지만 수행하고자 할 때 사용


위와 같은 동적 SQL을 작성하는 경우 경우에 따라 SQL 에러가 발생하는 케이스가 존재
불완전한 동적 SQL 구문을 해결하기 위해 Mybatis에서 지원하는 문법
<trim> : 쿼리 구문의 특정 부분을 없앨 때
<where> : 기존 쿼리의 WHERE절을 동적으로 구현할 때
<set> : 기존의 UPDATE SET절을 동적으로 구현할 때
또는 아래와 같은 WHERE 1=1 AND … 구문으로도 해결 가능하다. (실제 필드에서 가장 많이 활용하는 문법)
SELECT * FROM BOARD
WHERE 1=1
<if test="writer != null">
AND ID LIKE '%${writer}%'
</if>
<if test="title != null">
AND TITLE LIKE '%${title}%'
</if>
단순히 WHERE만을 추가하지만 만일 태그 안의 내용이 AND나 OR로 시작할 경우 ‘AND’ 또는 ‘OR’ 제거

태그 안의 내용이 완성될 때 처음 시작할 단어(prefix)와 시작 시 제거해야 할 단어(prefixOverrides)를 명시해 where와 같은 내용으로 구현

UPDATE하고자 하는 컬럼을 동적으로 포함시키기 위해 사용하며 SET 키워드를 붙이고 불필요한 콤마 제거

WHERE와 흡사하나 suffixOverrides속성을 ‘,’로 설정하여 구문의 마지막에 제거할 값 명시

동적 쿼리를 구현할 때 collection에 대한 반복처리 제공
| 속성 명 | 설명 |
|---|---|
| item | 반복 시 각 요소에 접근할 때 사용할 변수명입니다. |
| index | 반복되는 인덱스 값을 가리키는 변수입니다. 0부터 순차적으로 증가합니다. |
| collection | Mapper로 전달받은 파라미터 중 반복에 사용할 컬렉션 객체입니다.List 또는 배열(Array) 타입만 사용할 수 있습니다. |
| open | 반복 구문이 시작될 때 앞에 삽입할 문자열입니다. |
| separator | 반복되는 요소 사이에 삽입할 구분자 문자열입니다. |
| close | 반복 구문이 종료될 때 뒤에 삽입할 문자열입니다. |
특정 문장을 미리 생성하여 쿼리에 적용해야 할 경우 사용
_parameter를 통해 전달받은 값에 접근하여 구문 생성

<sql></sql>태그를 통해 미리 만들어 놓은 쿼리를 다른 쿼리에 주입 가능
이때 <include>를 활용하며, 만일 다른 값을 주입할 경우 <property> 활용
