- PR -

SELECT&INSERTの失敗について

1
投稿者投稿内容
fujie
会議室デビュー日: 2005/04/13
投稿数: 15
投稿日時: 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 = ? ";
ちょま吉
大ベテラン
会議室デビュー日: 2004/08/04
投稿数: 112
投稿日時: 2005-09-16 21:32
Connectionがオートコミットがtrueになってたりしませんか?
insLDM06でインサートされて、他の処理でレコードが削除される。
その後insLDM07が実行されるとか?
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-09-18 12:52
Connectionを取得しているgetConnectionメソッドの実装はどうなっているのでしょうか。
そこにバグがあって、一つのConnectionを複数のメソッドで同時に使っていたりしませんか?
Java僧
ぬし
会議室デビュー日: 2003/11/06
投稿数: 261
投稿日時: 2005-09-19 23:40
これ、servletなんですかね?formはインスタンス変数?
http://www.atmarkit.co.jp/fjava/rensai2/webopt04/webopt04.html
スレッドセーフにはなっていますか?

ConnectionのスコープはinsDB()だから良さそう・・・かな?

#テーブル名だとかValueObjectの名前がアレですねぇ・・・
fujie
会議室デビュー日: 2005/04/13
投稿数: 15
投稿日時: 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/05
投稿数: 127
投稿日時: 2005-09-22 15:36
根本的な解決にはならないと思いますが
マルチテーブルインサートを使ってはどうでしょうか?
http://oraclesqlpuzzle.hp.infoseek.co.jp/2-1-1.html


OracleSQLパズル
http://oraclesqlpuzzle.hp.infoseek.co.jp


ちょま吉
大ベテラン
会議室デビュー日: 2004/08/04
投稿数: 112
投稿日時: 2005-09-22 21:54
引用:
 ※ getConnection(Connection.TRANSACTION_SERIALIZABLE) のようにして
  使用します。DB更新の場合のみこのメソッドでコネクションを取得します。

  もしかして、このように設定した状態で、SELECT&INSERTは不可能なのでしょうか。

conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);


他のトランザクションレベルで試してみれば良いのではないでしょうか?

また、根本的な解決ではないのですが、selectしないで1つめのinsert文のように
すれば問題は発生しませんよね。(insertするデータはform等で用意されているのですから)
解決しない場合の選択肢にはなるかと思います。
fujie
会議室デビュー日: 2005/04/13
投稿数: 15
投稿日時: 2005-09-29 09:09
お返事をいただきありがとうございます。

参考にさせていただき、もう少し検討をしてみたいと思います。
ご意見、ご指摘をいただき、大変助かりました。

1

スキルアップ/キャリアアップ(JOB@IT)