S2JDBCでDialect指定忘れたばかりにID自動生成してもらえなくてハマるS2JDBCでID自動生成してもらえない
// ------------------
2008-12-30 12:52追記
id:taediumさんにご指摘いただきました。感謝です!
jdbc.diconだけ設定してs2jdbc.diconのdialect指定を忘れていたのが原因でした。
// ------------------
またライフハックネタでアプリを作り始める。
勉強を兼ねてScala+Lift・・・とか考えたけどまずScalaの習得からになるので今回はパス。
そこそこ小さなアプリなので、手軽に作れる素直にSAStruts + S2JDBC + HSQLDBで作り始める。
てか今のプロジェクトでSAStrutsが却下されてしまったので、SAStrutsでまともにモノを作るのは今回が初めてだったりしますが。
データ構造も単純だからデータインサートの部分くらいすぐできるだろうと思ってたら、さっそくエラー。メッセージが「エンティティ(Study)のIDプロパティ(id)の自動生成に失敗しました。」って。えー。
あれこれ試してみたものの、結局今日は原因を特定できずじまい。とりあえずSQLファイルにINSERT文を手書きして動くようにした。
// -------- 以下ソースの抜粋
テーブル定義
CREATE TABLE study ( id integer generated by default as identity ,study_date DATE NOT NULL ,name VARCHAR(100) NOT NULL ,plan_minute INTEGER ,plan_quantity INTEGER ,result_minute INTEGER ,result_quantity INTEGER ,comment VARCHAR(255) ,parent_id INTEGER );
エンティティ定義
@Entity public class Study implements Serializable, Cloneable { private static final long serialVersionUID = -7448008552713640531L; @Id @GeneratedValue @Column(insertable=false) // Columnアノテーションなしでもエラー public Integer id; @Temporal(TemporalType.DATE) public Date studyDate; public String name; public String comment; public int planMinute; public int planQuantity; public int resultMinute; public int resultQuantity; public Integer parentId; @Override public Study clone() { Study s = new Study(); s.id = null; s.name = name; s.comment = comment; s.studyDate = (Date) studyDate.clone(); s.planMinute = planMinute; s.planQuantity = planQuantity; s.resultMinute = resultMinute; s.resultQuantity = resultQuantity; s.parentId = parentId; return s; } @Override public String toString() { // デバッグ用途でオーバーライド }
結果のスタックトレースのメッセージは下記のもの
javax.servlet.ServletException: org.seasar.extension.jdbc.exception.IdGenerationFailedRuntimeException: [ESSR0738]エンティティ(Study)のIDプロパティ(id)の自動生成に失敗しました。
org.apache.struts.action.RequestProcessor.processException(RequestProcessor.java:535)
org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:433)
org.seasar.struts.action.S2RequestProcessor.process(S2RequestProcessor.java:125)
org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)
javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
org.seasar.extension.filter.RequestDumpFilter.doFilter(RequestDumpFilter.java:127)
org.seasar.framework.container.hotdeploy.HotdeployFilter.doFilter(HotdeployFilter.java:75)
org.seasar.framework.container.filter.S2ContainerFilter.doFilter(S2ContainerFilter.java:79)
org.seasar.struts.filter.RoutingFilter.forward(RoutingFilter.java:204)
org.seasar.struts.filter.RoutingFilter.doFilter(RoutingFilter.java:137)
org.seasar.framework.container.hotdeploy.HotdeployFilter.doFilter(HotdeployFilter.java:63)
org.seasar.framework.container.filter.S2ContainerFilter.doFilter(S2ContainerFilter.java:79)
org.seasar.extension.filter.EncodingFilter.doFilter(EncodingFilter.java:69)
org.seasar.framework.exception.SSQLException: [ESSR0072]SQLで例外(SQL=[insert into STUDY (STUDY_DATE, NAME, COMMENT, PLAN_MINUTE, PLAN_QUANTITY, RESULT_MINUTE, RESULT_QUANTITY, PARENT_ID) values (?, ?, ?, ?, ?, ?, ?, ?)], Message=[-20], ErrorCode=IM001, SQLState={3})が発生しました
当面は下記のSQLで回避。IDカラムを明示的にインサート対象から除外。HSQLDBのGUIマネージャで実行するとちゃんとインサート成功する。
INSERT INTO STUDY ( study_date ,name ,plan_minute ,plan_quantity ,result_minute ,result_quantity ,comment ,parent_id) VALUES ( /*studyDate*/'2009-01-01' ,/*name*/'new study' ,/*planMinute*/5 ,/*planQuantity*/10 ,/*resultMinute*/15 ,/*resultQuantity*/10 ,/*comment*/'too difficult' ,/*parentId*/NULL );
明日はもうちょっとだけ原因調べる。メッセージに従えば、ID自動生成の定義が悪いってことなんだろうけど。本家のチュートリアルとそう違ってないはずなんだけどなぁ。
// ------------------
2008-12-30 12:52追記その2
また「設定したつもり」という勘違いによる凡ミスで時間食った。
ノーモア勘違い。
// ------------------