2016年3月18日金曜日

H2の1.3系では、auto_incrementなカラムを持つテーブルへのバッチinsertが使いものにならない

H2の安定版の1.3系を使うと、バッチinsert後のgetGeneratedKeysが1レコードしか返さないため、データベースで設定された値を取得できない問題がある。

getGeneratedKeysのJavadocにも下の記述があるので、完全に仕様のようです。
Return a result set that contains the last generated auto-increment key
for this connection, if there was one. If no key was generated by the
last modification statement, then an empty result set is returned.
The returned result set only contains the data for the very last row.

試した結果

試したバージョンは、1.3.176となっています。
compile 'com.h2database:h2:1.3.176'

このコードを実行すると、バッチinsertで10レコード登録しているので、it.getInt(1)が10回標準出力に出力されるはずですが、実際には1回しか出力されません。
出力される値は、Javadocにあるように最後に採番された値の「it.getInt(1) = 10」となります。
jdbcDataSource.connection.use {connection ->
  connection.createStatement().use {statement ->
    statement.execute("create table test(id bigint auto_increment, name varchar(255))")
  }

  connection.prepareStatement("insert into test (name) values (?)").use { ps ->
    for (i in 1..10) {
      ps.setString(1, "name_$i")
      ps.addBatch();
    }
    ps.executeBatch()

    ps.generatedKeys.use {
      while (it.next()) {
        println("it.getInt(1) = ${it.getInt(1)}")
      }
    }
  }
}

ちなみに、Beta版の1.4系(現時点での最新の1.4.191)にするとこの問題は解消しています。