私はiBatis/JavaとPostgres8.3を使用しています。 ibatisで挿入を行うときは、IDを返す必要があります。
質問を説明するために次の表を使用します。CREATE TABLE sometable ( id serial NOT NULL, somefield VARCHAR(10) );
シーケンス_sometable_id_seq
_は、createステートメントを実行することで自動生成されます。
現時点では、次のSQLマップを使用しています。
_<insert id="insertValue" parameterClass="string" >
INSERT INTO sometable ( somefield ) VALUES ( #value# );
<selectKey keyProperty="id" resultClass="int">
SELECT last_value AS id FROM sometable_id_seq
</selectKey>
</insert>
_
これは、新しく挿入されたIDを取得するためのibatisの方法のようです。 Ibatisは最初にINSERTステートメントを実行し、その後、シーケンスに最後のIDを要求します。
これが多くの同時挿入で機能するかどうかは疑問です。 ( この質問で説明 )
Ibatisで次のステートメントを使用したいと思います。INSERT INTO sometable ( somefield ) VALUES ( #value# ) RETURNING id;
しかし、_<insert>
_ sqlMap ibatis内で使用しようとすると、IDが返されません。 _<selectKey>
_タグが必要なようです。
だからここに質問が来ます:
上記のステートメントをibatisで使用するにはどうすればよいですか?
<selectKey>
要素は<insert>
要素の子であり、その内容はメインのINSERT
の前に実行されますステートメント。 2つのアプローチを使用できます。
レコードを挿入した後にキーを取得します
このアプローチは、ドライバーによって異なります。これにはスレッド化が問題になる可能性があります。
レコードを挿入する前にキーを取得する
このアプローチはスレッドの問題を回避しますが、より多くの作業が必要です。例:
<insert id="insert">
<selectKey keyProperty="myId"
resultClass="int">
SELECT nextVal('my_id_seq')
</selectKey>
INSERT INTO my
(myId, foo, bar)
VALUES
(#myId#, #foo#, #bar#)
</insert>
Java側では、次のことができます
Integer insertedId = (Integer) sqlMap.insert("insert", params)
これにより、my_id_seq
シーケンスから選択されたキーが得られます。
簡単な例を次に示します。
<statement id="addObject"
parameterClass="test.Object"
resultClass="int">
INSERT INTO objects(expression, meta, title,
usersid)
VALUES (#expression#, #meta#, #title#, #usersId#)
RETURNING id
</statement>
そしてJavaコード:
Integer id = (Integer) executor.queryForObject("addObject", object);
object.setId(id);
この方法は、使用するよりも優れています: