データベースにレコードを挿入した後に、その自動採番された主キーIDを取得したいケースはよくあります。MyBatisでは、この要件をuseGeneratedKeys属性または<selectKey>要素を使って実現できます。
useGeneratedKeysによるID取得
最もシンプルな方法は、<insert>タグにuseGeneratedKeys="true"とkeyPropertyを指定することです。
<insert id="insertStudent" useGeneratedKeys="true" keyProperty="id" parameterType="Student">
INSERT INTO student(name, age, score) VALUES(#{name}, #{age}, #{score})
</insert>
この設定により、挿入後に生成されたIDが、渡されたオブジェクトのidフィールドに自動的にセットされます。ただし、対応するエンティティクラスにはsetId()およびgetId()メソッドが必須です。
<selectKey>によるID取得
別のアプローチとして、<selectKey>要素を使用して明示的にIDをクエリすることも可能です。これは特に、データベースが自動採番をサポートしていない場合や、カスタムロジックでIDを生成する際に有用です。
<insert id="insertStudent" parameterType="Student">
INSERT INTO student(name, age, score) VALUES(#{name}, #{age}, #{score})
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
</insert>
ここで注意すべき点:
order="AFTER"はINSERT実行後にSELECTを実行することを意味します。LAST_INSERT_ID()はMySQL専用の関数であり、直前に挿入されたレコードの自動採番IDを返します。- Oracleなどの他のDBでは、シーケンスを使用するなど異なるSQLが必要になります。
戻り値について
MyBatisのinsert操作の戻り値は、影響を受けた行数(通常は1)です。ID自体は戻り値ではなく、引数として渡したオブジェクトに直接セットされます。
Student student = new Student("example", 20, 90);
System.out.println("Before: " + student.getId()); // null or 0
studentMapper.insertStudent(student);
System.out.println("After: " + student.getId()); // 自動採番されたID
補足:MySQL接続時の注意点
MySQL 8.xを使用する際は、JDBC URL内の特殊文字をXMLで正しくエスケープする必要があります。
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8&serverTimezone=UTC"/>
また、依存ライブラリとして最新のMySQLコネクタを指定することが推奨されます。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>