こんにちは、wbsphere アプリケーションを tomcat に移植しています。同じサーバー上の 2 つのデータベースで作業する必要があり、Tomcat を atomikos transactionessential と統合しました。これは jta を使用した最初のプロジェクトであり、スキーマが同じサーバー上にあるため、xa と 2 フェーズ コミットは必要ないとオラクル データベース管理者から言われました。だから私はatomikosで非xaアプローチを使用しました。単一のスキーマでの次のコードは正常に機能します (コミットとロールバックは期待どおりです)。
utx.begin();
conn = //get connection
if (sAzione.equals("1"))
sql = "UPDATE parametri set valore =to_char(sysdate,'dd/mm/yyyy HH24:MI:ss') where id_parametri= 9 ";
//execute query
sql = "SELECT SEQ_LOTTO.nextval id FROM dual";
//other operations
sql = "INSERT INTO LOTTO (id_lotto, numero_lotto, id_area, id_stato_lavorazione, id_autore, id_tipo)";
sql = sql + " VALUES (" + id + ", " + numero + ", " + request.getParameter("idArea") + ",1,"+ session.getAttribute("id_anagrafica")+ "," + request.getParameter("idTipo") + ")";
//execute import and release connection
utx.commit();
別の場所では、次のオラクル関数が呼び出され、両方のスキーマを変更しようとすると、コード 1 が返されます。pl-slq はわかりませんが、戻り値は最初の delete で例外が発生したことを意味するように見えますが、2 番目の削除は実行されてコミットされます。誰かが私にこの関数の意味を説明できますか? 以下は、関数とそれを呼び出すコードです
create or replace FUNCTION FN_ELIMINA_RACC (idracc IN NUMBER, idlotto IN NUMBER)
RETURN NUMBER
IS
retvalue NUMBER (1);
BEGIN
retvalue := 1;
DELETE FROM npa_collaudo.documento_raccomandata
WHERE id_raccomandata = idracc;
retvalue := 2;
DELETE FROM raccomandata_out
WHERE id_racc_out = idracc;
retvalue := 3;
IF idlotto != 0
THEN
UPDATE lotto
SET numero_racc = numero_racc - 1
WHERE id_lotto = idlotto;
END IF;
retvalue := 0;
COMMIT;
RETURN retvalue;
EXCEPTION
WHEN OTHERS
THEN
RETURN retvalue;
END;
//the calling code
utx.begin();
//get connection
sql = "FN_ELIMINA_RACC(" + idRacc + ", " + idLotto + ");";
ret = connessioneDB.eseguiSP(sql);
if (!(ret == 0)){
throw new Exception("exception");
utx.commit();
//since it returns 1 an exception is raised and rollback gets called
助けてくれてありがとう
編集:この(ひどい)コードをさらに調査し、あなたの答えのおかげで、悪名高い「eseguiSP」にこれを見つけました:
//strSQL is "FN_ELIMINA_RACC(..."
DBOracle dbType = new DBOracle();
String SQL = "";
int retValue = 0;
SQL = " DECLARE ";
SQL = SQL + " ret NUMBER; ";
SQL = SQL + " BEGIN ";
SQL = SQL + " ret := " + strSQL;
SQL = SQL + " END; ";
try {
stmt = conn.prepareCall(SQL);
retValue = stmt.executeUpdate(SQL);
} catch (SQLException e) {
//retValue = false;
}
return retValue;
そして、私はそれを次のように変更しました:
c = ds.getConnection();
java.sql.CallableStatement cstmt = c.prepareCall("{?=call FN_ELIMINA_RACC(?,?)}");
cstmt.registerOutParameter(1,java.sql.Types.INTEGER);
cstmt.setInt(2, idRacc);
cstmt.setInt(3, idLotto);
cstmt.execute();
ret = cstmt.getInt(1);
今では正常に動作します (または少なくとも 0 を返します)。古いコードでは、raccomandata_out からレコードを削除しても、常に 1 が返されるのはなぜですか?