Spring4+JdbcTemplate+PostgreSQL で INSERT したときに自動生成された ID を取得する

こんにちは、鈴木です。

 

Spring4 の JdbcTemplate で INSERT したときに、DB 側で自動生成された値を取得する方法を調べました。

主キーを SERIAL 型にしておいて INSERT 時に値を自動生成させたり、レコードの作成日時を保持するカラムに「DEFAULT CURRENT_TIMESTAMP」などと指定することはあるのではないでしょうか。そのような INSERT 時に自動生成された値を取得したいと思います。

RDBMS ごとにやり方は異なると思いますが、今回は PostgreSQL の場合です。

 

データベースとテーブルを作る

まずはデータベースを作ります。

データベースができたら psql コマンドで接続できるはずです。

次にテーブルを作ります。何でもよいのですが、users テーブルを作ってみます。

id カラムは SERIAL 型にして、値が自動生成されるようにしています。

他のカラムは何でもよいのですが、名前と年齢を保持するカラムを作っておきました。

 

Maven でプロジェクトを作る

maven でプロジェクトを作ります。

pom.xml を編集します。「追加 - ここから」「追加 - ここまで」の間が追加した部分です。

 

とりあえず INSERT するコード

本題とは関係無いコードが多くなってしまうので、とりあえず INSERT するプログラムを書き、その後で必要な箇所をピックアップします。

App#run メソッドの中が、とりあえず INSERT するコードです。

INSERT するために JdbcTemplate#update メソッドを使っています。JdbcTemplate#update は INSERT や UPDATE, DELETE するときに使える割と汎用的なメソッドで、影響のあったレコード数を返します。つまり、JdbcTemplate#update メソッドでは自動生成された id の値を取得できません。

ということで、どうしましょう・・。

 

lastval 関数を使う方法

PostgreSQL には lastval という関数があります。これを使うことで現在のセッションで最後に生成された値(正確には nextval で取得された値)を取得することができます。

コードを書くと以下のようになります。

ちなみに lastval に似ている currval という関数もあります。currval は引数で指定したシーケンスの最後の値を返しますが、lastval は最後に nextval されたシーケンスの最後の値を返します。currval だとシーケンス名を指定する手間があるので、lastval を使うことにしました。

 

RETURNING 句を使う方法

別の方法として INSERT 文の最後に「RETURNING id」を加えた SQL を実行することで、INSERT しつつ自動生成された id の値を返すことができます。

コードにすると以下のようになります。

lastval を使う方法では INSERT する SQL と lastval を実行する SQL を分けて実行する必要がありましたが、この方法では 1 回の SQL で完結します。

 

比較する

どちらの方法が良いか比較してみます。

lastval 関数を使う方法

RETURNING 句を使う方法

  • RETURNING 句は PostgreSQL 8.2 からサポートされている。
    (see 「PostgreSQL 8.2.6文書 - INSERT」)
  • SQL の実行回数は増えない。
  • カラムの名前を気にする必要がある。(カラム名が piyo なら「RETURNING piyo」)

まとめ

まとめると、

  • RETURNING 句を使う方法が良い(実行する SQL が増えないので)。
  • PostgreSQL のバージョンが 8.2 未満の場合は lastval を使う方法。
  • SQL の実行回数が増えても問題にならない場合は lastval の方法が楽(カラム名を気にしなくて良いので)。

だと思います。

 

Comments are closed, but you can leave a trackback: Trackback URL.