2017-08-14 81 views
0

我正在使用Oracle DB和Hibernate的JavaEE/JPA管理事務,並且需要實現某種嵌套事務。據我所知,這種東西不是開箱即用的,但我應該可以使用保存點來達到這個目的。如何使用Hibernate Session.doWork(...)進行保存點/嵌套事務?

正如https://stackoverflow.com/a/7626387/173689建議我嘗試了以下內容:

@Transactional(value = TxType.REQUIRES_NEW) 
public boolean doImport(Import importer, Row row) throws ImportRowFailedException { 
    // stripped code ... 
    // We need to try different possibilities from which one may succeed... 
    // ...former failures must be rolled back! 
    for (Possibility poss : importer.getPossibilities()) { 
     if (this.tryPossibility(poss, row)) break; 
    } 
    // stripped code ... 
} 

public boolean tryPossibility(Possibility possibility, Row row) { 
    try { 
     Session session = this.em.unwrap(Session.class); 
     session.doWork(new Work() { 
      @Override 
      public void execute(Connection connection) throws SQLException { 
       Savepoint before = connection.setSavepoint(); 
       if (!possibility.importRow(row)) { 
        connection.rollback(before); 
        throw new ImportRowFailedException(); 
       } 
      } 
     }); 
    } 
    catch (ImportRowFailedException ex) { 
     return false; 
    } 
    return true; 
} 

connection.rollback(before)我得到以下異常:

Caused by: java.sql.SQLException: IJ031040: Connection is not associated with a managed connection: [email protected] 
    at org.jboss.jca.adapters.jdbc.WrappedConnection.lock(WrappedConnection.java:164) 
    at org.jboss.jca.adapters.jdbc.WrappedConnection.rollback(WrappedConnection.java:883) 

我該怎麼處理呢?

回答

0

最初的java.sql.SQLException: IJ031040似乎與我們進口時的特定結果有關。它後來被替換爲另一個java.sql.SQLException,它禁止管理事務回滾。但我終於可以通過發行本地SQL語句解決的問題:

// Mark the current state as SAVEPOINT... 
Session session = this.em.unwrap(Session.class); 
session.doWork(new Work() { 
    @Override 
    public void execute(Connection connection) throws SQLException { 
     connection.prepareStatement("SAVEPOINT TRY_POSSIBILITY").executeUpdate(); 
    } 
}); 

// 
// Do all the risky changes... verify... decide... 
// 

// Rollback to SAVEPOINT if necessary! 
session.doWork(new Work() { 
    @Override 
    public void execute(Connection connection) throws SQLException { 
     connection.prepareStatement("ROLLBACK TO SAVEPOINT TRY_POSSIBILITY").executeUpdate(); 
    } 
}); 

這使得內較大的一個「嵌套事務」,解決了我的問題。

相關問題