PostgreSQLとGenerationType.IDENTITYではまる。
Seasar2.2.40、PostgreSQL8.4/PostgreSQL8.3系で次のようなエラー。
- idは、SERIAL型。
- Entityクラスでは、@GeneratedValue(strategy = GenerationType.IDENTITY)を利用。
で、次のようなExceptionはいて落ちる。テーブル自体は、insertされているので、try/catchすれば気にならない...か(?)
Exception in thread "main" org.seasar.framework.exception.SQLRuntimeException: [ESSR0072]SQLで例外(SQL=[select currval('EMPLOYEE_ID_seq')], Message=[[ESSR0072]SQLで例外(SQL=[select currval('EMPLOYEE_ID_seq')], Message=[0], ErrorCode=55000, SQLState={3})が発生しました : [SQLで例外(Message=[ERROR: currval of sequence "employee_id_seq" is not yet defined in this session], ErrorCode=0, SQLState=55000)が発生しました。], [ERROR: currval of sequence "employee_id_seq" is not yet defined in this session], ErrorCode=0, SQLState=55000)が発生しました at org.seasar.framework.util.PreparedStatementUtil.executeQuery(PreparedStatementUtil.java:51) at org.seasar.extension.jdbc.id.IdentityIdGenerator.getGeneratedId(IdentityIdGenerator.java:119) at org.seasar.extension.jdbc.id.IdentityIdGenerator.postInsert(IdentityIdGenerator.java:78) at org.seasar.extension.jdbc.query.AutoInsertImpl.postExecute(AutoInsertImpl.java:250) at org.seasar.extension.jdbc.query.AbstractAutoUpdate.executeInternal(AbstractAutoUpdate.java:126) at org.seasar.extension.jdbc.query.AbstractAutoUpdate.execute(AbstractAutoUpdate.java:90) at test.a.AMain.run(AMain.java:29) at test.a.AMain.main(AMain.java:50) Caused by: org.seasar.framework.exception.SSQLException: [ESSR0072]SQLで例外(SQL=[select currval('EMPLOYEE_ID_seq')], Message=[0], ErrorCode=55000, SQLState={3})が発生しました at org.seasar.extension.jdbc.impl.PreparedStatementWrapper.wrapException(PreparedStatementWrapper.java:72) at org.seasar.extension.jdbc.impl.PreparedStatementWrapper.wrapException(PreparedStatementWrapper.java:67) at org.seasar.extension.jdbc.impl.PreparedStatementWrapper.executeQuery(PreparedStatementWrapper.java:83) at org.seasar.framework.util.PreparedStatementUtil.executeQuery(PreparedStatementUtil.java:49) ... 7 more Caused by: org.postgresql.util.PSQLException: ERROR: currval of sequence "employee_id_seq" is not yet defined in this session at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2062) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1795) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257) at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:479) at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:367) at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:271) at org.seasar.extension.jdbc.impl.PreparedStatementWrapper.executeQuery(PreparedStatementWrapper.java:81) ... 8 more
エラーは、currvalが設定されていないよーというエラー。仕様的(PostgreSQLの)には、currvalする前にnextvalしないといけないのでnextvalをしていないと仮定するならば、納得がいくけど…。
サンプルコード
package test.a; import java.io.*; import java.util.*; import org.seasar.extension.jdbc.*; import org.seasar.framework.container.S2Container; import org.seasar.framework.container.factory.SingletonS2ContainerFactory; public class AMain { public JdbcManager jdbcManager; public void run() { Employee emp1 = new Employee(); emp1.name = "HelloWorld!!!"; jdbcManager.insert(emp1).execute(); jdbcManager.insert(emp1).execute(); }; public static void main(String args[]) { SingletonS2ContainerFactory.init(); S2Container container = SingletonS2ContainerFactory.getContainer(); AMain amain = (AMain) container.getComponent(AMain.class); amain.run(); container.destroy(); }; };
とりあえず、解放が見つからないのでGenerationType.SEQUENCEで試すかな...。
追記
トランザクション制御を忘れていたのが原因。
<component name="AMain" class="text.a.AMain"> <aspect>j2ee.requiredTx</aspect> </component>
あー。疲れた。