1. SQL 명령어 정의 태그
기본적인 데이터베이스 조작 문을 XML 파일 내에 선언할 때 사용하는 태그입니다. 각 쿼리 종류별로 고유한 속성을 가지며, 파라미터와 반환값의 타입을 명확히 정의해야 합니다.
<select>: 데이터를 조회하는 문장.id는 네임스페이스 내 고유 식별자,parameterType은 입력값 유형,resultType또는resultMap은 조회 결과를 매핑할 대상 클래스를 지정합니다. 컬렉션 반환 시에는泛型(제네릭) 타입의 기본형을 입력해야 합니다.<insert>,<delete>,<update>: 생성, 삭제, 수정 작업을 수행합니다. 주로parameterType만으로 파라미터 타입을 정의하며,useGeneratedKeys나keyProperty를 조합하면 자동 발급된 PK를 자바 객체에 주입할 수 있습니다.
<select id="findUserByPk" parameterType="Long" resultType="com.app.dto.UserDTO">
SELECT user_seq, login_id, email, join_date FROM users WHERE user_seq = #{pk}
</select>
<insert id="insertUser" parameterType="com.app.vo.UserVO" useGeneratedKeys="true" keyProperty="userSeq">
INSERT INTO users (login_id, email, role)
VALUES (#{loginId}, #{email}, #{role})
</insert>
<delete id="removeUser" parameterType="Long">
DELETE FROM users WHERE user_seq = #{pk}
</delete>
<update id="updateUserRole" parameterType="com.app.vo.UserVO">
UPDATE users SET role = #{newRole}, updated_at = CURRENT_TIMESTAMP WHERE user_seq = #{userSeq}
</update>
2. 결과 집합과 자바 객체 매핑 (ResultMap)
테이블 컬럼명과 자바 클래스 필드명이 일치하지 않거나, 대소문자 차이, 특수 문자가 포함된 경우 명시적으로 필드를 연결해야 합니다. <resultMap>는 이러한 불일치를 해소하고 복잡한 중첩 구조나 조인 결과를 정교하게 바인딩하는 역할을 합니다.
id속성: 기본키에 해당하는 필드 매핑. 성능 최적화를 위해 반드시 지정해야 합니다.result속성: 일반 컬럼과 DTO/Entity 필드 연결. 필요 시jdbcType을 명시하여 NULL 처리 오류를 방지합니다.
<resultMap id="UserDetailMap" type="com.app.dto.UserDTO">
<id property="seq" column="USER_SEQ" jdbcType="BIGINT"/>
<result property="username" column="LOGIN_ID"/>
<result property="contactEmail" column="EMAIL_ADDR"/>
<result property="registrationDt" column="JOIN_DATE" jdbcType="TIMESTAMP"/>
<result property="accountStatus" column="STATUS_FLAG" jdbcType="INTEGER"/>
</resultMap>
<select id="getUserDetail" resultMap="UserDetailMap" parameterType="Long">
SELECT USER_SEQ, LOGIN_ID, EMAIL_ADDR, JOIN_DATE, STATUS_FLAG
FROM users WHERE user_seq = #{pk}
</select>
3. 동적 SQL 제어문
실행 시점의 파라미터 값에 따라 쿼리 구조를 유연하게 변경해야 할 때 사용합니다. MyBatis의 핵심 기능으로, OGNL(expression) 기반 테스트 구문을 제공합니다.
<if>: 조건이 참일 때만 해당 SQL절을 삽입합니다. 주로 필터 조건이나 업데이트 대상 필드 선택에 활용됩니다.<foreach>: List, Array, Map 등의 컬렉션을 순회하여 SQL 조각을 반복 생성합니다.BATCH_insert나IN조건 구축에 필수적입니다.<choose>, <when>, <otherwise>: Java의switch-case구조와 동일합니다. 여러 조건 중 첫 번째로 만족하는when절만 실행되며, 모두 불일경우otherwise가 fallback 됩니다.
<if test="keyword != null and keyword != ''">
AND login_id LIKE CONCAT('%', #{keyword}, '%')
</if>
<select id="findUsersByIds" resultMap="UserDetailMap">
SELECT user_seq, login_id FROM users WHERE user_seq IN
<foreach item="targetSeq" collection="idsList" open="(" separator="," close=")">
#{targetSeq}
</foreach>
</select>
<select id="applyFlexibleFilter" resultMap="UserDetailMap">
SELECT * FROM users
<where>
<choose>
<when test="activeOnly">
AND account_status = 'ENABLED'
</when>
<when test="registeredAfter != null">
AND join_date >= #{registeredAfter}
</when>
<otherwise>
AND deleted_at IS NULL
</otherwise>
</choose>
</where>
</select>
4. SQL 절 서식 자동 조정 (Clause Formatting)
동적 조건이混杂될 때 발생하는 문법 오류(WHERE AND 또는 끝없는 ,)를 자동으로 치유하거나 감싸주는 헬퍼 태그들입니다.
<where>: 내부에 유효한 SQL절이 하나 이상 포함되면WHERE키워드를 자동으로 붙이고, 선두의AND/OR연산자를 분리해 줍니다.<set>:UPDATE문에서SET关键字를 관리합니다. trailing comma(최종 쉼표)를 자동으로 제거하며, 조건이 하나도 충족되지 않으면SET절 자체를 생략합니다.<trim>:<where>와<set>를 직접 구현하는 범용 도구입니다.prefix,suffix,prefixOverrides,suffixOverrides속성으로 전후 공백/연산자를 자유롭게 제어할 수 있습니다.
<select id="dynamicSearch" resultMap="UserDetailMap">
SELECT user_seq, login_id FROM users
<where>
<if test="departmentId != null">
AND dept_code = #{departmentId}
</if>
<if test="keyword != null and keyword != ''">
AND email LIKE '%' || #{keyword} || '%'
</if>
</where>
</select>
<update id="partialUpdateUser">
UPDATE users
<set>
<if test="displayName != null">display_name = #{displayName},</if>
<if test="contactPhone != null">phone_number = #{contactPhone},</if>
<if test="isPublic != null">profile_visibility = #{isPublic}</if>
</set>
WHERE user_seq = #{targetSeq}
</update>
<update id="customTrimUpdate">
UPDATE users
<trim prefix="SET " suffixOverrides=", ">
<if test="role != null">role = #{role},</if>
<if test="score != null">experience_score = #{score},</if>
</trim>
WHERE user_seq = #{targetSeq}
</update>
5. SQL 코드 재사용 패턴
복수 개의 쿼리에서 공통으로 사용되는 컬럼 리스트나 조건절 블록을 추출하여 중복을 제거하고 유지보수를 용이하게 하는 패턴입니다.
<sql>: 재사용 가능한 SQL 단위를id로 정의합니다. 동적 지시어를 포함해도 무방합니다.<include>: 정의된<sql>블록을refid로 인라인 삽입합니다.<with-param>를 통해 값을 전달할 수도 있습니다.
<!-- 공통 검색 필드 정의 -->
<sql id="CommonSelectColumns">
user_seq, login_id, display_name, phone_number, is_active
</sql>
<!-- 공통 필터 조건 정의 -->
<sql id="BaseFilterConditions">
WHERE 1=1
<trim suffixOverrides="AND OR">
<if test="minAge != null">AND age >= #{minAge}</if>
<if test="maxAge != null">AND age <= #{maxAge}</if>
<if test="regionCd != null">AND region_cd = #{regionCd}</if>
</trim>
</sql>
<!-- 재사용 예시: 전체 조회 -->
<select id="listAllUsers" resultMap="UserDetailMap">
SELECT
<include refid="CommonSelectColumns"/>
FROM users
<include refid="BaseFilterConditions"/>
ORDER BY user_seq DESC
</select>
<!-- 재사용 예시: 페이징 쿼리 -->
<select id="getPagedUsers" resultMap="UserDetailMap">
SELECT u.* FROM (
SELECT rownum as rn, base.* FROM (
SELECT
<include refid="CommonSelectColumns"/>
FROM users
<include refid="BaseFilterConditions"/>
) base
WHERE rownum <= #{endRow}
) u WHERE rn > #{startRow}
</select>