arrow_upward
본문 바로가기
Database

[PostgreSQL] MyBatis에서 Returning 사용법

by dawncode 2024. 5. 3.

 

PostgreSQL은 Returning이라는 기능으로 DML처리 시 변경되는 컬럼의 값을 리턴받을 수 있다.

 

INSERT INTO post (title, content) 
VALUES ('Returning', 'PK값을 리턴받을 수 있다.')
RETURNING post_id;

-- 결과
post_id
--------
9

 

이 기능을 통해서 MyBatis의 태그를 대체해서 사용할 수 있다.
MySQL에서 사용했던 방법과 PostgreSQL의 사용방법을 비교하여 확인해본다.



MyBatis 에서 사용하기

비즈니스 로직을 처리할 때 부모테이블이나 Insert 되는 테이블의 auto_increment되는 테이블의 PK 값을 알아야 할 필요가 있어서 MyBatis의 SelectKey 기능을 사용한다.

PostgreSQL은 SelectKey 기능을 사용하지 않고 Insert되는 PK의 시퀀스 값을 얻어올 수 있다.



MySQL 사용 방식

 

<insert id="save">
    INSERT INTO 
        table_ex (
            col1, 
            col2, 
            created_at
        ) 
    VALUES (
        #{col1}, 
        #{col2}, 
        now(), 
    <selectKey keyProperty="tableId" order="AFTER" resultType="Long">
        SELECT 
            LAST_INSERT_ID()
    </selectKey>
<insert>

 

MySQL에서 Insert 되는 테이블의 PK 값을 얻기 위해서 keyProperty 를 통해서 리턴될 키를 지정해주면, 프로퍼티와 일치하는 키값으로 Auto_increment된 시퀀스 값이 매핑되어 들어가있게 된다.



PostgreSQL Returning 사용

PostgreSQL 에서는 Returning 기능을 통해서 DML로 수정되는 테이블의 값을 리턴받을 수 있다.

<!-- 에러
<insert id="savePost" >
    INSERT INTO
        post (
            title, 
            CONTENT
        ) 
        VALUES (
        #{title}, 
        #{content})
    RETURNING post_id
</insert> -->

<select id="savePost" resultType="Integer">
    INSERT INTO
        post (
            title, 
            CONTENT
        ) 
        VALUES (
        #{title}, 
        #{content})
    RETURNING post_id
</select>

<select id="updatePost" resultType="HashMap">
    UPDATE test.POST SET
        title = #{title},
        content = #{content},
        updated_at = now()
    WHERE
        post_id = #{postId}
    RETURNING title, post_id
</select>

 

주의할 점은 insert 문을 사용할 때 보통 명시적인 insert 태그를 사용하는데 <insert>, <update>, <delete> 태그와 같이 DML을 위한 태그는 resultType이 없고, 기본적으로 DML로 처리된 row를 리턴하기 때문에 Returning 기능과 DML 전용 태그를 사용하게 되면 기존 리턴되는 처리되는 ROW 수의 값과 충돌이나서 -1을 리턴하게 된다.

Returning 기능은 MyBatis의 <select> 태그로 사용해야 하며, PK값만 받을 수 있는 것이 아닌 테이블의 전체 컬럼 중 원하는 컬럼을 선택하여 리턴할 수 있다.

<selectKey>와 다른점은 값을 리턴받는 것이기 때문에 selectKey처럼 DML이 처리되고 KeyProperty로 지정한 파라미터로 값이 자동 주입되는 것이 아닌, resultType의 리턴 값을 통해서 받아야 한다.

@Test
void savePostTest() {    
    Map<String, Object> param = new HashMap<>();
    param.put("title", "리턴 값 테스트");
    param.put("content", "Return Value Test");
    param.put("post_id", null);

    Integer result = customService.savePost(param);

    log.info("param : {}", param);
    log.info("savePost ReturnValue : {}", result);

    assertThat(result).isNotNull();
}

/* 결과
param : {post_id=null, title=리턴 값 테스트, content=Return Value Test}
savePost ReturnValue : 8
*/

 

테스트 결과를 확인하면 주입된 파라미터에는 값이 들어오지 않았고 리턴 값은 시퀀스 값이 나타난 것을 확인할 수 있다.

select 문에 사용하면 조회 쿼리와 리턴 값이 충돌나기 때문에 사용하면 안된다.

 

 

 

참조

'Database' 카테고리의 다른 글

[PostgreSQL] Invalid Transaction Termination 에러  (0) 2024.04.18