1. 概要

このクイックチュートリアルでは、純粋なJDBCを使用して最後に自動生成されたキーを取得する方法を説明します。

2. 設定

SQLクエリを実行できるようにするために、インメモリH2データベースを使用します。

次に、最初のステップとして、Mavenの依存関係を追加しましょう。

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.200</version>
</dependency>

また、2列しかない非常に単純なテーブルを使用します。

public class JdbcInsertIdIntegrationTest {

    private static Connection connection;

    @BeforeClass
    public static void setUp() throws Exception {
        connection = DriverManager.getConnection("jdbc:h2:mem:generated-keys", "sa", "");
        connection
          .createStatement()
          .execute("create table persons(id bigint auto_increment, name varchar(255))");
    }

    @AfterClass
    public static void tearDown() throws SQLException {
        connection
          .createStatement()
          .execute("drop table persons");
        connection.close();
    }

    // omitted
}

ここでは、生成されたキー インメモリデータベースに接続し、その中にpeopleという名前のテーブルを作成しています。

3. 生成されたキーフラグを返す

自動生成後にキーをフェッチする1つの方法は、 Statement.RETURN_GENERATED_KEYSprepareStatement()メソッドに渡すことです。

String QUERY = "insert into persons (name) values (?)";
try (PreparedStatement statement = connection.prepareStatement(QUERY, Statement.RETURN_GENERATED_KEYS)) {
    statement.setString(1, "Foo");
    int affectedRows = statement.executeUpdate();
    assertThat(affectedRows).isPositive();

    // omitted
} catch (SQLException e) {
    // handle the database related exception appropriately
}

クエリを準備して実行した後、 PreparedStatementgetGeneratedKeys()メソッドを呼び出してIDを取得できます。

try (ResultSet keys = statement.getGeneratedKeys()) {
    assertThat(keys.next()).isTrue();
    assertThat(keys.getLong(1)).isGreaterThanOrEqualTo(1);
}

上に示したように、最初に next()メソッドを呼び出して結果カーソルを移動します。 次に、 getLong()メソッドを使用して最初の列を取得し、同時にlongに変換します。

さらに、通常のステートメントで同じ手法を使用することもできます。

try (Statement statement = connection.createStatement()) {
    String query = "insert into persons (name) values ('Foo')";
    int affectedRows = statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
    assertThat(affectedRows).isPositive();

    try (ResultSet keys = statement.getGeneratedKeys()) {
        assertThat(keys.next()).isTrue();
        assertThat(keys.getLong(1)).isGreaterThanOrEqualTo(1);
    }
}

また、 try-with-resources を広範囲に使用して、コンパイラーが後からクリーンアップできるようにしていることにも言及しておく価値があります。

4. 戻り列

結局のところ、クエリを発行した後、JDBCに特定の列を返すように要求することもできます。 これを行うには、列名の配列を渡す必要があります。

try (PreparedStatement statement = connection.prepareStatement(QUERY, new String[] { "id" })) {
    statement.setString(1, "Foo");
    int affectedRows = statement.executeUpdate();
    assertThat(affectedRows).isPositive();

    // omitted
}

上に示したように、指定されたクエリを実行した後、id列の値を返すようにJDBCに指示しています。 前の例と同様に、後でidをフェッチできます。

try (ResultSet keys = statement.getGeneratedKeys()) {
    assertThat(keys.next()).isTrue();
    assertThat(keys.getLong(1)).isGreaterThanOrEqualTo(1);
}

単純なステートメントでも同じアプローチを使用できます。

try (Statement statement = connection.createStatement()) {
    int affectedRows = statement.executeUpdate("insert into persons (name) values ('Foo')", 
      new String[] { "id" });
    assertThat(affectedRows).isPositive();

    try (ResultSet keys = statement.getGeneratedKeys()) {
        assertThat(keys.next()).isTrue();
        assertThat(keys.getLong(1)).isGreaterThanOrEqualTo(1);
    }
}

5. 結論

このクイックチュートリアルでは、純粋なJDBCを使用してクエリを実行した後に生成されたキーをフェッチする方法を説明しました。

いつものように、すべての例はGitHubから入手できます。