- - PR -
SELECT&INSERTの失敗について
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2005-09-15 20:32
お世話になります。
下記のようなソースで、insDB()を実行すると、 insLDM07()において throw new LogicalError("E00337", "insLDM07処理", String.valueOf(cnt) + "件"); が発生し、原因が分からず困っています。 何かご指摘を頂けませんでしょうか。 ----------------------------------- 詳細情報:・insLDM06()は問題無く成功しています。 ・insLDM07()の実行結果は、以下のとおりです。(情報をエラーに出力しています。) cnt=0 form.getKanriNo()=性常値がセットされています ⇒ 実行結果件数が0件のため、INSERT文中のSELECT件数が0件ということだと 思うのですが、前処理(insLDM06)は成功しているため、理由がわかりません・・・。 発生頻度:50回に1回の割合で、このエラーが発生します。 毎回ではありません。 環境:Tomcat4.1.24 Oracle 9i jdk1.4.2_06 ----------------------------------- public void insDB(LGD0203FR01 form, DkDate sysDate, String ipAddr, String userNo) throws Exception{ Connection conn = null; try { conn = getConnection(Connection.TRANSACTION_SERIALIZABLE); insLDM06(conn, form, sysDate, ipAddr, userNo); insLDM07(conn, form, sysDate, ipAddr, userNo); conn.commit(); }catch(LogicalError le) { throw new LogicalError(le.getMessageId(), le.getParam1(), le.getParam2()); }catch(SQLException se) { throw new DbError(se.getMessage()); }catch (Exception e) { throw e; }finally { if(conn != null){ try { conn.rollback(); conn.close(); } catch (SQLException e){ e.printStackTrace(); }} } } private void insLDM06(Connection conn, LGD0203FR01 form, DkDate sysDate, String ipAddr, String userNo) throws Exception{ PreparedStatement ps = null; int para = 1; try{ ps = conn.prepareStatement(INSERT_LDM06); ps.setString(para ++, form.getKaiCode()); ps.setString(para ++, form.getKanriNo()); ps.setString(para ++, form.getMosiCustCode()); ps.setInt(para ++, Integer.parseInt(form.getCmRirekiNo())); ps.setString(para ++, trimOrPadS(form.getKkSekuCode())); ps.setTimestamp(para ++, sysDate); ps.setString(para ++, ipAddr); ps.setString(para ++, userNo); ps.setTimestamp(para ++, sysDate); ps.setString(para ++, ipAddr); ps.setString(para, userNo); int cnt = ps.executeUpdate(); if(cnt != 1){ throw new LogicalError("E00337", "insLDM06処理", String.valueOf(cnt) + "件"); } }finally{ if(ps != null){ try { ps.close();ps = null; } catch (SQLException e){ e.printStackTrace(); }} } } private void insLDM07(Connection conn, LGD0203FR01 form, DkDate sysDate, String ipAddr, String userNo) throws Exception{ PreparedStatement ps = null; int para = 1; try{ ps = conn.prepareStatement(INSERT_LDM07); ps.setTimestamp(para ++, sysDate); ps.setString(para ++, ipAddr); ps.setString(para ++, userNo); ps.setTimestamp(para ++, sysDate); ps.setString(para ++, ipAddr); ps.setString(para ++, userNo); ps.setString(para ++, form.getKaiCode()); // --- KEY ps.setString(para, form.getKanriNo()); // --- KEY int cnt = ps.executeUpdate(); if(cnt != 1){ throw new LogicalError("E00337", "insLDM07処理", String.valueOf(cnt) + "件:" + form.getKanriNo()); } }finally{ if(ps != null){ try { ps.close();ps = null; } catch (SQLException e){ e.printStackTrace(); }} } } public final static String INSERT_LDM06 = "insert into LDM06 " + "(KK_KAI_CODE, KK_KANRI_NO, KK_RIREKINO_MAX, KK_CUST_CODE, " + " KK_CUST_RIREKINO, KK_SEKU_CODE, " + " KK_INSDATE, KK_INSIP, KK_INSUSERNO, KK_MODDATE, KK_MODIP, KK_MODUSERNO, " + " KK_DELDATE, KK_DELIP, KK_DELUSERNO) " + "values(?, ?, 1, ?, " + " ?, ?, " + " ?, ?, ?, ?, ?, ?, " + " null, ' ', ' ') "; public final static String INSERT_LDM07 = "insert into LDM07 "+ "select " + " KK_KAI_CODE, KK_KANRI_NO, KK_RIREKINO_MAX, KK_CUST_CODE, " + " KK_CUST_RIREKINO, KK_SEKU_CODE, " + " ?, ?, ?, ?, " + " ?, ?, null, ' ', ' ' " + "from LDM06 " + "where KK_KAI_CODE = ? " + " and KK_KANRI_NO = ? "; | ||||
|
投稿日時: 2005-09-16 21:32
Connectionがオートコミットがtrueになってたりしませんか?
insLDM06でインサートされて、他の処理でレコードが削除される。 その後insLDM07が実行されるとか? | ||||
|
投稿日時: 2005-09-18 12:52
Connectionを取得しているgetConnectionメソッドの実装はどうなっているのでしょうか。
そこにバグがあって、一つのConnectionを複数のメソッドで同時に使っていたりしませんか? | ||||
|
投稿日時: 2005-09-19 23:40
これ、servletなんですかね?formはインスタンス変数?
http://www.atmarkit.co.jp/fjava/rensai2/webopt04/webopt04.html スレッドセーフにはなっていますか? ConnectionのスコープはinsDB()だから良さそう・・・かな? #テーブル名だとかValueObjectの名前がアレですねぇ・・・ | ||||
|
投稿日時: 2005-09-21 19:14
お返事が遅くなり申し訳ございません。
ご指摘を頂き、ありがとうございます。 ■ちょま吉様 >Connectionがオートコミットがtrueになってたりしませんか? >insLDM06でインサートされて、他の処理でレコードが削除される。 >その後insLDM07が実行されるとか? オートコミットはfalseとしているため、この点については問題無いと思います。 ■uk様 >Connectionを取得しているgetConnectionメソッドの実装はどうなっているのでしょうか。 >そこにバグがあって、一つのConnectionを複数のメソッドで同時に使っていたりしませんか? getConnectionメソッドは以下のようになっています。 public Connection getConnection(int level) throws Exception { Connection conn = null; try { conn = (LGAS00.getDataSource()).getConnection(); conn.commit(); conn.setAutoCommit(false); conn.setTransactionIsolation(level); checkConnectionLeak(conn); } catch(SQLException e) { if(conn != null) { conn.close(); } throw new SQLException("LGAS00.getConnection() " + e.getMessage()); } catch(Exception e) { if(conn != null) { conn.close(); } throw new Exception(this.getClass().getName() + ":getConnection() " + e.getMessage()); } return conn; } ※ getConnection(Connection.TRANSACTION_SERIALIZABLE) のようにして 使用します。DB更新の場合のみこのメソッドでコネクションを取得します。 もしかして、このように設定した状態で、SELECT&INSERTは不可能なのでしょうか。 conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); ■Java僧様 >これ、servletなんですかね?formはインスタンス変数? はい。Servletです。 formはインスタンス変数です。 また、この事象は、システムにログインしている人が複数人の場合にも発生しましたし、 1人の場合にも発生しました。 毎回同じ登録を行っているにも関わらず、すごく稀にこの事象が発生します。 発生時の登録データを比較しても、原因が分かりません。。。 | ||||
|
投稿日時: 2005-09-22 15:36
根本的な解決にはならないと思いますが
マルチテーブルインサートを使ってはどうでしょうか? http://oraclesqlpuzzle.hp.infoseek.co.jp/2-1-1.html OracleSQLパズル http://oraclesqlpuzzle.hp.infoseek.co.jp | ||||
|
投稿日時: 2005-09-22 21:54
他のトランザクションレベルで試してみれば良いのではないでしょうか? また、根本的な解決ではないのですが、selectしないで1つめのinsert文のように すれば問題は発生しませんよね。(insertするデータはform等で用意されているのですから) 解決しない場合の選択肢にはなるかと思います。 | ||||
|
投稿日時: 2005-09-29 09:09
お返事をいただきありがとうございます。
参考にさせていただき、もう少し検討をしてみたいと思います。 ご意見、ご指摘をいただき、大変助かりました。 |
1