public final R run() throws Exception {
        if (getCurrent() != null) {
            if (logger.isDebugEnabled())
                logger.debug("Starting new inner transaction " + name);
            connection = getCurrent().connection;
            try {
                return execute();
            } finally {
                connection = null;
                if (logger.isDebugEnabled())
                    logger.debug("Finished inner transaction " + name);
            }
        } else {
            try {
                if (logger.isDebugEnabled())
                    logger.debug("Starting new transaction " + name);
                R result = null;
                currentTransaction.set(this);
                connection = aquireConnection(false);
                for (int seqNr = 1;; seqNr++) {
                    try {
                        result = execute();
                        if (modificatory) {
                            logger.debug("Trying to commit");
                            connection.commit();
                            logger.debug("Transaction {} commited", name);
                        } else {
                            logger.debug("Txn is read only - rolling back");
                            connection.rollback();
                            logger.debug("Transaction {} rolled back", name);
                        }
                        break;
                    } catch (SQLException e) {
                        if (logger.isDebugEnabled())
                            logger.debug("Transaction " + name + " will be rolled back due to SQLException: " + e.toString(), e);
                        try {
                            connection.rollback();
                        } catch (SQLException e2) {
                            logger.warn("Rollback failed:" + e2.toString(), e2);
                        }
                        final RetryAction ra = check4retry(e, seqNr);
                        if (logger.isDebugEnabled())
                            logger.debug("RetryAction=" + ra);
                        if (ra == RetryAction.noRetry) {
                            throw e;
                        } else if (ra == RetryAction.retryWithNewConnection) {
                            logger.warn("Transaction " + name + " will be retried with new connection due to SQLException " + e.toString());
                            try {
                                connection.close();
                            } catch (SQLException e2) {
                                logger.warn("close failed:" + e2.toString(), e2);
                            }
                            connection = aquireConnection(true);
                        } else {
                            logger.error("Unexpected RetryAction " + ra);
                            assert false : "Unexpected RetryAction " + ra;
                        }
                    } catch (Exception e) {
                        if (logger.isDebugEnabled())
                            logger.debug("Transaction " + name + " will be rolled back due to Exception: " + e.toString(), e);
                        try {
                            connection.rollback();
                        } catch (SQLException e2) {
                            logger.warn("Rollback failed:" + e2.toString(), e2);
                        }
                        throw e;
                    }
                }
                return result;
            } finally {
                currentTransaction.remove();
                if (connection != null) {
                    connection.close();
                }
                if (logger.isDebugEnabled())
                    logger.debug("Finished transaction " + name);
            }
        }
    }
public final R run ( ) throws Exception { if ( getCurrent ( ) != null ) { if ( logger . isDebugEnabled ( ) ) logger . debug ( "Starting new inner transaction " + name ) ; connection = getCurrent ( ) . connection ; try { return execute ( ) ; } finally { connection = null ; if ( logger . isDebugEnabled ( ) ) logger . debug ( "Finished inner transaction " + name ) ; } } else { try { if ( logger . isDebugEnabled ( ) ) logger . debug ( "Starting new transaction " + name ) ; R result = null ; currentTransaction . set ( this ) ; connection = aquireConnection ( false ) ; for ( int seqNr = 1 ; ; seqNr ++ ) { try { result = execute ( ) ; if ( modificatory ) { logger . debug ( "Trying to commit" ) ; connection . commit ( ) ; logger . debug ( "Transaction {} commited" , name ) ; } else { logger . debug ( "Txn is read only - rolling back" ) ; connection . rollback ( ) ; logger . debug ( "Transaction {} rolled back" , name ) ; } break ; } catch ( SQLException e ) { if ( logger . isDebugEnabled ( ) ) logger . debug ( "Transaction " + name + " will be rolled back due to SQLException: " + e . toString ( ) , e ) ; try { connection . rollback ( ) ; } catch ( SQLException e2 ) { logger . warn ( "Rollback failed:" + e2 . toString ( ) , e2 ) ; } final RetryAction ra = check4retry ( e , seqNr ) ; if ( logger . isDebugEnabled ( ) ) logger . debug ( "RetryAction=" + ra ) ; if ( ra == RetryAction . noRetry ) { throw e ; } else if ( ra == RetryAction . retryWithNewConnection ) { logger . warn ( "Transaction " + name + " will be retried with new connection due to SQLException " + e . toString ( ) ) ; try { connection . close ( ) ; } catch ( SQLException e2 ) { logger . warn ( "close failed:" + e2 . toString ( ) , e2 ) ; } connection = aquireConnection ( true ) ; } else { logger . error ( "Unexpected RetryAction " + ra ) ; assert false : "Unexpected RetryAction " + ra ; } } catch ( Exception e ) { if ( logger . isDebugEnabled ( ) ) logger . debug ( "Transaction " + name + " will be rolled back due to Exception: " + e . toString ( ) , e ) ; try { connection . rollback ( ) ; } catch ( SQLException e2 ) { logger . warn ( "Rollback failed:" + e2 . toString ( ) , e2 ) ; } throw e ; } } return result ; } finally { currentTransaction . remove ( ) ; if ( connection != null ) { connection . close ( ) ; } if ( logger . isDebugEnabled ( ) ) logger . debug ( "Finished transaction " + name ) ; } } }
This function implements error handling (i.e. transaction rollbacks in
case of exceptions etc.), and automatic retries in case of deadlocks or
timeouts.