2012-03-28 5 views
0

한 테이블에서 몇 가지 테이블을 수정해야합니다. 그들은 모두 성공해야하거나 모두 실패해야합니다. 한 작업이 실패하면 모두 실패합니다. 나는 다음과 같은 것을 가지고있다 :언제 java.sql.Connection.rollback()을 호출해야합니까?

나는이 과정에서 문제가 발생했을 때 rollback()을 호출해야하는지 궁금하다.

기타 정보 : 연결 풀링을 사용하고 있습니다. 위의 예제에서, 나는 또한 각 PreparedStatement를 finally 문을 사용하여 닫고, 간결하게하기 위해 생략했다.

답변

1

당신은 rollback()를 호출 할 필요는 없습니다 감사합니다. commit()을 완료하지 않고 연결이 닫히면 롤백됩니다.

conn에서 null까지 설정할 필요는 없습니다. conn이 초기화 된 후에 try 블록이 시작되기 때문에 (...은 null로 평가 될 수 없다고 가정 할 때) != nullfinally에 필요하지 않습니다.

+0

좋아 너무도 업데이트와 함께, 그 CONN를 반영하기 위해 예 (null의 경우도있다) 업데이트 I 여전히 롤백()을 호출 할 필요가 없습니까? 감사합니다 – user291701

+0

맞습니다, 당신은 롤백을 호출 할 필요가 없습니다. 앞의 예제에서'conn'가'try' 전에 초기화되었습니다. –

+0

이것은 사실이 아닙니다. 변경 사항을 롤백하려면 연결에서 롤백을 호출해야합니다. 자동으로 롤백되지는 않습니다. 내 대답을 볼 수 있지만 커밋을 호출하기 전에 예외를 throw하여 쉽게 테스트 할 수 있습니다. –

0

"커밋"을 호출하면 트랜잭션이 커밋됩니다. 삽입/갱신 문이 여러 개 있고 그 중 하나가 실패하면 확약하면 데이터베이스에 확약하지 못한 삽입/갱신이 발생합니다. 그래서 네, 다른 진술을 db에 커밋하지 않으려면 롤백을 호출해야합니다. autocommit을 false로 설정하여 본질적으로 수행중인 작업은 여러 명령문을 함께 커밋하거나 롤백 할 수있게하는 것입니다. 그렇지 않으면 각각의 개별 문장이 자동으로 커밋됩니다.

+0

내 대답을 명확히하기 위해 여러 문장을 사용한다고 가정합니다. 예를 들어 하나의 명령문 만 있으면 자동으로 롤백됩니다.그러나 Java 코드에서 여러 개의 명령문이 호출 된 경우 롤백해야합니다. – DavidB

+0

여러 문장 (변수가 잘 재사용 됨)이 있음을 보여주기 위해 업데이트되었습니다. 여전히 롤백이 필요합니까? 감사합니다 – user291701

+0

당신은 방위를 코딩해야합니다. 위의 코드는 단일 연결로 작동하며 명시 적으로 롤백을 호출 할 필요가 없습니다. 그러나 연결 풀이있는 환경에이 코드를 삽입하면 연결이 풀에서 자주 닫히지 않으므로 다른 트랜잭션이 동일한 연결을 다시 사용하므로 이상한 동작이 발생합니다. 개인적으로 롤백은 성능 히트 (rollbacks가 비싸다)를 일으키는 것으로 확실히 식별 할 수 있고 작업중인 환경의 트랜잭션 동작을 완전히 이해하지 않는 한 항상 사용합니다. – DavidB

0

예 어떤 명령문이 실패하거나 커밋을 호출하기 전에 예외를 감지 한 경우 롤백을 호출해야합니다. 이것은 오래된 게시물이지만 허용 된 대답은 잘못되었습니다. 커밋 전에 예외를 throw하고 수동으로 롤백하지 않으면 삽입이 데이터베이스에 계속 남아 있음을 관찰하여 직접 시도 할 수 있습니다. 다큐먼트에서

JDBC 문서 https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html#call_rollback

예 올바른 사용법

public void updateCoffeeSales(HashMap<String, Integer> salesForWeek) 
    throws SQLException { 

    PreparedStatement updateSales = null; 
    PreparedStatement updateTotal = null; 

    String updateString = 
     "update " + dbName + ".COFFEES " + 
     "set SALES = ? where COF_NAME = ?"; 

    String updateStatement = 
     "update " + dbName + ".COFFEES " + 
     "set TOTAL = TOTAL + ? " + 
     "where COF_NAME = ?"; 

    try { 
     con.setAutoCommit(false); 
     updateSales = con.prepareStatement(updateString); 
     updateTotal = con.prepareStatement(updateStatement); 

     for (Map.Entry<String, Integer> e : salesForWeek.entrySet()) { 
      updateSales.setInt(1, e.getValue().intValue()); 
      updateSales.setString(2, e.getKey()); 
      updateSales.executeUpdate(); 
      updateTotal.setInt(1, e.getValue().intValue()); 
      updateTotal.setString(2, e.getKey()); 
      updateTotal.executeUpdate(); 
      con.commit(); 
     } 
    } catch (SQLException e) { 
     JDBCTutorialUtilities.printSQLException(e); 
     if (con != null) { 
      try { 
       System.err.print("Transaction is being rolled back"); 
       con.rollback(); 
      } catch(SQLException excep) { 
       JDBCTutorialUtilities.printSQLException(excep); 
      } 
     } 
    } finally { 
     if (updateSales != null) { 
      updateSales.close(); 
     } 
     if (updateTotal != null) { 
      updateTotal.close(); 
     } 
     con.setAutoCommit(true); 
    } 
} 
관련 문제