Develop

[MyBatis] selectKey를 사용하여 생성된 키값을 Java에서 리턴받는 방법

issuemaker99 2024. 12. 31. 13:24
728x90

실무에서는 데이터베이스에 새 레코드를 삽입하면서 생성된 키값(예: AUTO_INCREMENT 값)을 객체에 매핑하고, 이를 서비스나 다른 로직에서 활용하는 일이 흔합니다. 이번 글에서는 실무에서 자주 사용하는 패턴을 중심으로 selectKey를 이용해 키값을 가져오는 방법을 설명합니다.


selectKey 실무 활용 시 주의점

  1. 데이터베이스의 자동 키 생성 방식 파악
    MySQL, PostgreSQL, Oracle 등 데이터베이스마다 키 생성 방식이 다릅니다.
    예:
    • MySQL: AUTO_INCREMENT + LAST_INSERT_ID()
    • PostgreSQL: SERIAL 또는 RETURNING id
    • Oracle: SEQUENCE
  2. 키값 매핑 확인
    MyBatis에서 keyProperty가 올바른 필드에 매핑되는지 검증합니다. 필드명과 DB 매퍼 설정이 정확히 일치해야 합니다.
  3. 트랜잭션 관리
    트랜잭션 내에서 키값을 가져오는 로직은 commit 전까지 유효해야 하므로, selectKey는 SQL 실행 순서에 따라 작동하는지 검토합니다.

실무 예제: selectKey를 활용한 키값 활용

1. 요구사항

  • 유저 정보를 User 테이블에 저장.
  • 저장 후 생성된 id를 활용해 로그 테이블(UserLog)에 삽입 기록 추가.

2. 데이터베이스 테이블 설계

CREATE TABLE User (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL
);

CREATE TABLE UserLog (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    action VARCHAR(50) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES User (id)
);

 


3. Java 객체 설계

public class User {
    private Integer id;
    private String name;
    private String email;

    // Getters and Setters
    // ...
}

public class UserLog {
    private Integer id;
    private Integer userId;
    private String action;
    private LocalDateTime createdAt;

    // Getters and Setters
    // ...
}

 


4. MyBatis 매퍼 XML

(1) User 삽입 매퍼

<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
    <selectKey keyProperty="id" resultType="int" order="AFTER">
        SELECT LAST_INSERT_ID()
    </selectKey>
    INSERT INTO User (name, email) VALUES (#{name}, #{email})
</insert>

 

(2) UserLog 삽입 매퍼

<insert id="insertUserLog" parameterType="UserLog">
    INSERT INTO UserLog (user_id, action) VALUES (#{userId}, #{action})
</insert>

 


5. 매퍼 인터페이스

public interface UserMapper {
    void insertUser(User user);
    void insertUserLog(UserLog userLog);
}

 


6. 서비스 로직 구현

import org.apache.ibatis.session.SqlSession;

public class UserService {
    public void createUserWithLog(String name, String email) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        try {
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

            // 1. 유저 생성
            User newUser = new User();
            newUser.setName(name);
            newUser.setEmail(email);

            userMapper.insertUser(newUser); // 이 시점에 newUser.getId() 값이 설정됨
            System.out.println("Generated User ID: " + newUser.getId());

            // 2. 생성된 유저 ID를 기반으로 로그 작성
            UserLog userLog = new UserLog();
            userLog.setUserId(newUser.getId());
            userLog.setAction("User Created");

            userMapper.insertUserLog(userLog);

            // 트랜잭션 커밋
            sqlSession.commit();
        } catch (Exception e) {
            sqlSession.rollback();
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }
    }
}

 


실무 사용 포인트

1. 트랜잭션 보장

  • 유저 삽입과 로그 기록은 한 트랜잭션에서 처리해야 데이터 정합성이 유지됩니다.
  • 예제에서는 SqlSession을 통해 트랜잭션을 관리하고, 실패 시 롤백합니다.

2. 다중 매퍼 활용

  • insertUser로 생성된 ID를 UserLog 삽입 시 활용합니다. 이 과정은 다중 테이블 조작이 필요한 실무에서 매우 흔합니다.

3. 로그 추가 활용

  • 생성된 ID로 다른 비즈니스 로직(예: 알림 발송, 초기 설정 저장 등)을 처리할 수 있습니다.

결과 출력

Generated User ID: 101
UserLog inserted with User ID: 101
LIST