DB

MyBatis 新規データ登録 オートインクリメント 自動採番 ID 取得

MyBatisでDBにデータ新規登録するときに、
登録したデータのIDを返却する方法が分からなく調べたことがあるので、
メモしておきたいと思います。

前提として、Primary KeyなどオートインクリメントされるDB構造になっている想定での内容です。

https://mybatis.org/mybatis-3/ja/sqlmap-xml.html#insert_update_and_delete

検証環境・バージョン

  • MacOS:Sonoma 14.6
  • Amazon Corretto:17
  • SpringBoot:3.4.0
  • MyBatis:3.0.4
  • MyBatis generator-core:1.4.0
  • IntelliJ IDEA:2024.2 (Ultimate Edition)

useGeneratedKeys オプション

MyBatisは、XMLタグで実行SQLを定義したり、
アノテーションでSQL実行処理を実装することができます。
INSERT処理実装箇所で、useGeneratedKeys=trueというオプションを指定すると、
INSERTを実行したデータのIDを取得することができます。

  • アノテーションで指定する例
@Insert("insert into user (name, age) values (#{name}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insertUserReturnId(User user);
  • XMLタグで指定する例
<insert id="insertUserReturnIdXml" parameterType="example.com.springboot_mybatis.model.User" useGeneratedKeys="true" keyProperty="id">
  insert into user (name, age)
  values (#{name}, #{age})
</insert>

モデルクラス利用例

モデルクラスをINSERT処理に引数として渡してIDを取得する例です。


package example.com.springboot_mybatis.model;

public class User {
    private Integer id;
    private String name;
    private Integer age;
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

package example.com.springboot_mybatis.service;

import example.com.springboot_mybatis.model.User;
import example.com.springboot_mybatis.mapper.UserMapperCustom;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserService {

    @Autowired
    private UserMapperCustom userMapperCustom;

    @Transactional(readOnly = false)
    public Integer insertUserSample1() {
        User user = new User();
        user.setName("User1");
        user.setAge(30);
        userMapperCustom.insertUserReturnId(user);
        return user.getId(); // 生成されたデータのIDが返却される
    }

    @Transactional(readOnly = false)
    public Integer insertUserSample2() {
        User user = new User();
        user.setName("User2");
        user.setAge(40);
        userMapperCustom.insertUserReturnIdXml(user);
        return user.getId(); // 生成されたデータのIDが返却される
    }
}

package example.com.springboot_mybatis.mapper;

import example.com.springboot_mybatis.model.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

@Component
public interface UserMapperCustom {

    // INSERT処理 アノテーション実装
    @Insert("insert into user (name, age) values (#{name}, #{age})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    void insertUserReturnId(User user);
    // INSERT処理 XML実装
    void insertUserReturnIdXml(User user);
}

<!-- INSERT処理 XML実装例 -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="example.com.springboot_mybatis.mapper.UserMapperCustom">
 <insert id="insertUserReturnIdXml" parameterType="example.com.springboot_mybatis.model.User" useGeneratedKeys="true" keyProperty="id">
 insert into user (name, age)
 values (#{name}, #{age})
 </insert>
</mapper>

利用するモデルクラスは、自動生成で作成したモデルクラス等でも実装可能です。


Mapパラメータ受取例

INSERTの実装オプションとしてkeyProperty=”Mapキー”を指定すると、
新規登録されたデータの一部をMap形式で受け取ることができます。


package example.com.springboot_mybatis.service;

import example.com.springboot_mybatis.model.User;
import example.com.springboot_mybatis.mapper.UserMapperCustom;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserService {

    @Transactional(readOnly = false)
    public Integer insertUserSample3() {
        Map<String, Object> idMap = new HashMap<>();
        userMapperCustom.insertUserReturnIdMap("User3", 50, idMap);
        BigInteger id = (BigInteger) idMap.get("id"); // 生成されたデータのIDが返却される
        return id.intValue();
    }

    @Transactional(readOnly = false)
    public Integer insertUserSample4() {
        Map<String, Object> idMap = new HashMap<>();
        userMapperCustom.insertUserReturnIdMapXml("User3", 50, idMap);
        BigInteger id = (BigInteger) idMap.get("id"); // 生成されたデータのIDが返却される
        return id.intValue();
    }
}
package example.com.springboot_mybatis.mapper;

import example.com.springboot_mybatis.model.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

@Component
public interface UserMapperCustom {

    // INSERT処理 アノテーション実装
    @Insert("insert into user (name, age) values (#{name}, #{age})")
    @Options(useGeneratedKeys = true, keyProperty = "idMap.id")
    void insertUserReturnIdMap(@Param("name") String name, @Param("age") int age, @Param("idMap") Map<String, Object> idMap);

    // INSERT処理 XML実装
    void insertUserReturnIdMapXml(@Param("name") String name, @Param("age") int age, @Param("idMap") Map<String, Object> idMap);
}
<!-- INSERT処理 XML実装例 -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="example.com.springboot_mybatis.mapper.UserMapperCustom">
 <insert id="insertUserReturnIdMapXml" parameterType="map" useGeneratedKeys="true" keyProperty="idMap.id">
   insert into user (name, age)
   values (#{name}, #{age})
 </insert>
</mapper>

[補足] 次に採番されるIDを取得する

PostgreSQLの実装例

PostgreSQLの場合、nextval関数で次に採番されるIDを取得できます。
アノテーション実装、XML実装のどちらでも取得できます。


package example.com.springboot_mybatis.mapper;

import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;

@Component
public interface UserMapperCustom {
    @Select("SELECT nextval('user_id_seq')")
    Integer getNextSequenceId();
}
<mapper namespace="example.com.springboot_mybatis.mapper.UserMapperCustom">
  <select id="getNextSequenceId" resultType="java.lang.Integer">
   SELECT nextval('user_id_seq')
  </select>
</mapper>

MySQLの実装例

<mapper namespace="example.com.springboot_mybatis.mapper.UserMapperCustom">
    <select id="getNextAutoIncrementId" resultType="java.lang.Integer">
        SELECT AUTO_INCREMENT 
        FROM information_schema.TABLES 
        WHERE TABLE_SCHEMA = 'your_database_name' 
        AND TABLE_NAME = 'user'
    </select>
</mapper>

今回のメモは以上となります。

MyBatisはあまり利用したことがなく、
基本的な機能なども把握できていなかったりしますので、
調べた際にはメモしておきたいと思います。

都内でエンジニアをやっています。 2017年に脱サラ(法人設立)しました。 仕事で調べたことや、気になったことをメモしています。
投稿を作成しました 176

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連投稿

検索語を上に入力し、 Enter キーを押して検索します。キャンセルするには ESC を押してください。

トップに戻る