155 lines
4.1 KiB
Markdown
155 lines
4.1 KiB
Markdown
---
|
|
name: mybatis-mapper
|
|
description: "MyBatis Mapper XML 쿼리를 작성하거나 수정한다. 쿼리 최적화, 동적 SQL, 페이징, 다중 DB 호환 쿼리 작업 시 사용한다. 'SQL 작성', '쿼리 추가', 'Mapper 수정', '조회 조건 추가' 요청에 적용."
|
|
---
|
|
|
|
# MyBatis Mapper XML 작성 스킬
|
|
|
|
## Mapper 파일 위치
|
|
|
|
```
|
|
src/main/resources/egovframework/mapper/kccf/{module}/{Module}_SQL.xml
|
|
```
|
|
|
|
## namespace 규칙
|
|
|
|
```xml
|
|
<mapper namespace="kccf.{module}.dao.{Module}DAO">
|
|
```
|
|
|
|
## 핵심 패턴
|
|
|
|
### 페이징 목록 조회 (Oracle/Altibase 기준)
|
|
|
|
```xml
|
|
<select id="select{Module}List" parameterType="{Module}VO" resultType="{Module}VO">
|
|
SELECT A.*
|
|
, ROW_NUMBER() OVER (ORDER BY A.REG_DTTM DESC) AS rn
|
|
, COUNT(*) OVER () AS totCnt
|
|
FROM TB_{MODULE} A
|
|
WHERE A.DELETE_AT = 'N'
|
|
<where>
|
|
<if test="searchField != null and searchField != ''">
|
|
AND A.FIELD = #{searchField}
|
|
</if>
|
|
<if test="searchNm != null and searchNm != ''">
|
|
AND A.NM LIKE '%' || #{searchNm} || '%'
|
|
</if>
|
|
</where>
|
|
ORDER BY A.REG_DTTM DESC
|
|
</select>
|
|
```
|
|
|
|
**MySQL/MariaDB 페이징 변형:**
|
|
```sql
|
|
SELECT A.*, @rownum := @rownum + 1 AS rn, total.cnt AS totCnt
|
|
FROM TB_{MODULE} A, (SELECT COUNT(*) cnt FROM TB_{MODULE} WHERE DELETE_AT='N') total
|
|
WHERE A.DELETE_AT = 'N'
|
|
ORDER BY A.REG_DTTM DESC
|
|
LIMIT #{pageSize} OFFSET #{offset}
|
|
```
|
|
|
|
### 동적 조건 (where 절)
|
|
|
|
```xml
|
|
<where>
|
|
<!-- NULL 또는 빈문자열 체크 -->
|
|
<if test="field != null and field != ''">
|
|
AND COL = #{field}
|
|
</if>
|
|
<!-- IN 절 -->
|
|
<if test="codeList != null and codeList.size() > 0">
|
|
AND CODE IN
|
|
<foreach item="item" collection="codeList" open="(" separator="," close=")">
|
|
#{item}
|
|
</foreach>
|
|
</if>
|
|
<!-- 기간 조건 -->
|
|
<if test="searchStartDate != null and searchStartDate != ''">
|
|
AND REG_DTTM >= #{searchStartDate}
|
|
</if>
|
|
<if test="searchEndDate != null and searchEndDate != ''">
|
|
AND REG_DTTM <= #{searchEndDate}
|
|
</if>
|
|
</where>
|
|
```
|
|
|
|
### INSERT / UPDATE
|
|
|
|
```xml
|
|
<insert id="insert{Module}" parameterType="{Module}VO">
|
|
INSERT INTO TB_{MODULE} (
|
|
ID, NM, CODE, DELETE_AT, REG_USER_ID, REG_DTTM, UPD_USER_ID, UPD_DTTM
|
|
) VALUES (
|
|
#{id}, #{nm}, #{code}, 'N', #{regUserId}, SYSDATE, #{updUserId}, SYSDATE
|
|
)
|
|
</insert>
|
|
|
|
<!-- 부분 UPDATE (set 태그) -->
|
|
<update id="update{Module}" parameterType="{Module}VO">
|
|
UPDATE TB_{MODULE}
|
|
<set>
|
|
<if test="nm != null">NM = #{nm},</if>
|
|
<if test="code != null">CODE = #{code},</if>
|
|
UPD_USER_ID = #{updUserId},
|
|
UPD_DTTM = SYSDATE
|
|
</set>
|
|
WHERE ID = #{id}
|
|
</update>
|
|
```
|
|
|
|
### 소프트 삭제 (KCCF 표준)
|
|
|
|
```xml
|
|
<update id="delete{Module}" parameterType="{Module}VO">
|
|
UPDATE TB_{MODULE}
|
|
SET DELETE_AT = 'Y'
|
|
, UPD_USER_ID = #{updUserId}
|
|
, UPD_DTTM = SYSDATE
|
|
WHERE ID = #{id}
|
|
</update>
|
|
```
|
|
|
|
### ID 채번 (시퀀스)
|
|
|
|
```xml
|
|
<!-- Oracle: 시퀀스 사용 시 -->
|
|
<select id="get{Module}IdSeq" resultType="String">
|
|
SELECT TO_CHAR(SEQ_{MODULE}.NEXTVAL, 'FM0000000000') FROM DUAL
|
|
</select>
|
|
|
|
<!-- 시퀀스 없을 때: MAX + 1 방식 -->
|
|
<select id="get{Module}IdSeq" resultType="String">
|
|
SELECT LPAD(NVL(MAX(TO_NUMBER(ID)), 0) + 1, 10, '0')
|
|
FROM TB_{MODULE}
|
|
</select>
|
|
```
|
|
|
|
## XML 특수문자 이스케이프
|
|
|
|
| 문자 | XML 표현 |
|
|
|------|---------|
|
|
| `<` | `<` |
|
|
| `>` | `>` |
|
|
| `&` | `&` |
|
|
| `<=` | `<=` |
|
|
| `>=` | `>=` |
|
|
|
|
또는 CDATA 블록:
|
|
```xml
|
|
<if test="val != null">
|
|
<![CDATA[ AND COL <= #{val} ]]>
|
|
</if>
|
|
```
|
|
|
|
## DB 방언 주의사항
|
|
|
|
| 기능 | Oracle/Altibase | MySQL/MariaDB | PostgreSQL |
|
|
|------|----------------|---------------|-----------|
|
|
| 현재시각 | `SYSDATE` | `NOW()` | `NOW()` |
|
|
| 문자 연결 | `\|\|` | `CONCAT()` | `\|\|` |
|
|
| NULL 대체 | `NVL()` | `IFNULL()` | `COALESCE()` |
|
|
| 행번호 | `ROWNUM` / `ROW_NUMBER()` | `ROW_NUMBER()` (8.0+) | `ROW_NUMBER()` |
|
|
| 페이징 | `ROWNUM` 서브쿼리 | `LIMIT OFFSET` | `LIMIT OFFSET` |
|
|
| 더미테이블 | `FROM DUAL` | 생략 | 생략 |
|