본문 바로가기
DB

[DB] MyBatis resultMap 자동 생성 (Oracle 기반, PL/SQL 스크립트)

by 늑인 2025. 4. 10.

 

🧩 MyBatis resultMap 자동 생성

     (Oracle 기반, PL/SQL 스크립트)

MyBatis를 사용할 때 가장 귀찮은 것 중 하나가 바로 resultMap 작성입니다.
특히 테이블 컬럼이 많거나 VO가 많을수록 반복 작업이 많아지고 실수도 잦아집니다.

그래서 Oracle에서 테이블 구조를 기반으로 resultMap을 자동으로 생성해주는 PL/SQL 스크립트를 정리해봤습니다.

✅ 특징

  • resultMap XML 구조 자동 생성
  • PK 컬럼은 <id> 태그로 생성
  • 컬럼명은 camelCase로 자동 변환
  • 컬렉션/association은 제외하고 단일 테이블 기준으로만 생성

💻 사용 방법

  1. Oracle SQL Developer, Toad 등에서 실행
  2. v_target_table 변수에 대상 테이블명을 넣고 실행
SET SERVEROUTPUT ON;
DECLARE
    v_result_line VARCHAR2(4000);
    v_last_column_id NUMBER;
    v_property_name VARCHAR2(1000);
    v_target_table VARCHAR2(30) := UPPER('BUSI_OVSEE'); -- 여기서 테이블명 설정
BEGIN
    -- 마지막 컬럼 ID 조회
    SELECT MAX(COLUMN_ID)
    INTO v_last_column_id
    FROM USER_TAB_COLUMNS
    WHERE TABLE_NAME = v_target_table;

    DBMS_OUTPUT.PUT_LINE('    <resultMap id="resultMapId" type="com.example.' || INITCAP(LOWER(v_target_table)) || 'VO">');

    FOR col IN (
        SELECT utc.COLUMN_NAME, utc.COLUMN_ID,
               CASE WHEN EXISTS (
                   SELECT 1 FROM USER_CONS_COLUMNS ucc
                   JOIN USER_CONSTRAINTS uc
                   ON ucc.CONSTRAINT_NAME = uc.CONSTRAINT_NAME
                   WHERE uc.CONSTRAINT_TYPE = 'P'
                     AND uc.TABLE_NAME = utc.TABLE_NAME
                     AND ucc.COLUMN_NAME = utc.COLUMN_NAME
               ) THEN 'Y' ELSE 'N' END AS IS_PK
        FROM USER_TAB_COLUMNS utc
        WHERE utc.TABLE_NAME = v_target_table
        ORDER BY utc.COLUMN_ID
    ) LOOP
        -- camelCase property name 생성
        SELECT 
            LOWER(SUBSTR(REPLACE(INITCAP(REPLACE(LOWER(col.COLUMN_NAME), '_', ' ')), ' ', ''), 1, 1)) ||
            SUBSTR(REPLACE(INITCAP(REPLACE(LOWER(col.COLUMN_NAME), '_', ' ')), ' ', ''), 2)
        INTO v_property_name
        FROM DUAL;

        IF col.IS_PK = 'Y' THEN
            v_result_line := '        <id property="' || v_property_name || '" column="' || col.COLUMN_NAME || '"/>';
        ELSE
            v_result_line := '        <result property="' || v_property_name || '" column="' || col.COLUMN_NAME || '"/>';
        END IF;

        DBMS_OUTPUT.PUT_LINE(v_result_line);
    END LOOP;

    -- collection + 내부 result 자동 생성
    FOR child IN (
        SELECT * FROM (
            SELECT c_fk.TABLE_NAME AS CHILD_TABLE, a.COLUMN_NAME
            FROM USER_CONSTRAINTS c_pk
            JOIN USER_CONSTRAINTS c_fk ON c_pk.CONSTRAINT_NAME = c_fk.R_CONSTRAINT_NAME
            JOIN USER_CONS_COLUMNS a ON c_fk.CONSTRAINT_NAME = a.CONSTRAINT_NAME
            WHERE c_pk.CONSTRAINT_TYPE = 'P'
              AND c_pk.TABLE_NAME = v_target_table
        )
    ) LOOP
        SELECT 
            LOWER(SUBSTR(REPLACE(INITCAP(REPLACE(LOWER(child.CHILD_TABLE), '_', ' ')), ' ', ''), 1, 1)) ||
            SUBSTR(REPLACE(INITCAP(REPLACE(LOWER(child.CHILD_TABLE), '_', ' ')), ' ', ''), 2)
        INTO v_property_name
        FROM DUAL;

        DBMS_OUTPUT.PUT_LINE('        <collection property="' || v_property_name || 'List" ofType="com.example.' || INITCAP(LOWER(child.CHILD_TABLE)) || 'VO">');

        FOR subcol IN (
            SELECT utc.COLUMN_NAME,
                   CASE WHEN EXISTS (
                       SELECT 1 FROM USER_CONS_COLUMNS ucc
                       JOIN USER_CONSTRAINTS uc
                       ON ucc.CONSTRAINT_NAME = uc.CONSTRAINT_NAME
                       WHERE uc.CONSTRAINT_TYPE = 'P'
                         AND uc.TABLE_NAME = utc.TABLE_NAME
                         AND ucc.COLUMN_NAME = utc.COLUMN_NAME
                   ) THEN 'Y' ELSE 'N' END AS IS_PK
            FROM USER_TAB_COLUMNS utc
            WHERE utc.TABLE_NAME = child.CHILD_TABLE
            ORDER BY utc.COLUMN_ID
        ) LOOP
            SELECT 
                LOWER(SUBSTR(REPLACE(INITCAP(REPLACE(LOWER(subcol.COLUMN_NAME), '_', ' ')), ' ', ''), 1, 1)) ||
                SUBSTR(REPLACE(INITCAP(REPLACE(LOWER(subcol.COLUMN_NAME), '_', ' ')), ' ', ''), 2)
            INTO v_property_name
            FROM DUAL;

            IF subcol.IS_PK = 'Y' THEN
                DBMS_OUTPUT.PUT_LINE('            <id property="' || v_property_name || '" column="' || subcol.COLUMN_NAME || '"/>');
            ELSE
                DBMS_OUTPUT.PUT_LINE('            <result property="' || v_property_name || '" column="' || subcol.COLUMN_NAME || '"/>');
            END IF;
        END LOOP;

        DBMS_OUTPUT.PUT_LINE('        </collection>');
    END LOOP;

    DBMS_OUTPUT.PUT_LINE('    </resultMap>');
END;
/

 

 

 

🧪 출력 예시 (EMP 테이블 기준)

<resultMap id="resultMapId" type="com.example.EmpVO">
    <id property="empNo" column="EMP_NO"/>
    <result property="busiCode" column="BUSI_CODE"/>
    <result property="comNum" column="COM_NUM"/>
    <result property="memberid" column="MEMBERID"/>
    <result property="empDate" column="EMP_DATE"/>
    <result property="empIns" column="EMP_INS"/>
    <result property="part" column="PART"/>
    <result property="state" column="STATE"/>
    <result property="memName" column="MEM_NAME"/>

    <!-- 하위 테이블과의 관계 (예: EMP -> EMP_HISTORY) -->
    <collection property="empHistories" ofType="com.example.EmpHistoryVO">
        <id property="historyId" column="HISTORY_ID"/>
        <result property="empNo" column="EMP_NO"/>
        <result property="changeDate" column="CHANGE_DATE"/>
        <result property="status" column="STATUS"/>
    </collection>
</resultMap>

 

 

🔚 마무리

  • 이 스크립트를 활용하면 MyBatis VO 매핑 작업 시간을 크게 줄일 수 있습니다.
  • 추후 VO 클래스 자동 생성이나 SQL + resultMap 묶음 생성도 확장 가능합니다.

'DB' 카테고리의 다른 글

[DB] sqldeveloper 자동완성 등록  (0) 2024.10.30
[DB] MERGE INTO  (0) 2024.07.31
[DB] 셀프 조인  (0) 2024.07.31
[DB] 신입들이 읽어 보면 좋을 사이트 링크  (0) 2024.05.27
[DB] 댓글 계층형 쿼리  (0) 2024.04.03