안녕하세요 나는 Tomcat에 wbsphere 애플리케이션을 포팅하고 있습니다. 동일한 서버에서 두 개의 데이터베이스로 작업해야하며 atomikos transactionessential으로 tomcat을 통합했습니다. 이것은 jta가있는 첫 번째 프로젝트이며 oracle dba는 스키마가 동일한 서버에 있으므로 xa와 2 단계 커밋이 필요 없다고 말했습니다. 그래서 나는 atomikos와 non-xa 접근법을 사용했습니다. 다음 오라클 함수가 호출 모두 스키마를 변경하려고 도착, 다른 곳에서다른 스키마의 테이블을 업데이트하는 oracle 함수를 작성하는 방법
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를 모른다. 그러나 반환 값은 첫 번째 삭제에서 예외가 있었음을 의미하지만 두 번째 삭제는 실행되고 커밋된다. 누군가이 기능의 의미를 설명 할 수 있습니까? 이 (끔찍한) 코드로 더 조사하고 답변 덕분에, 내가 이걸 발견했습니다 : 아래의 기능과
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);
N 그것은 잘 작동합니다 (또는 적어도 0을 반환합니다). 왜 raccomandata_out에서 레코드를 삭제하더라도 코드의 이전 부분은 항상 1을 반환합니까?
게시물에 감사드립니다. 몇 가지 사실을 눈치 챘습니다 (편집 참조). 나는 그것이 어디 executeIpdate (레코드 1 삭제) 호출 때문에 returnig 1 것 같아요. –
와우. 익명 블록은 아무 것도하지 않으므로 함수에서 반환 된'ret' 값은 무시됩니다. 'retValue = 1'은 아마도'executeUpdate()'에서 영향을받은 행의 수를 반환하지만 아마도 3 개 ('idLotto! = 0')의 DML 문을 다루는 방법에 대해서는 확신하지 못합니다. idLotto가 0이 아니고 유효하지 않거나 삭제할 것이 없으며'idLotto'가 0 인 경우 아마도 0을 반환합니다. 그럼에도 불구하고 왜 세미콜론이 필요한지 설명합니다 ... –