1 package org.hibernate.transaction; 3 4 import java.sql.SQLException ; 5 import java.util.ArrayList ; 6 import java.util.List ; 7 8 import javax.transaction.Status ; 9 import javax.transaction.Synchronization ; 10 11 import org.apache.commons.logging.Log; 12 import org.apache.commons.logging.LogFactory; 13 14 import org.hibernate.HibernateException; 15 import org.hibernate.Transaction; 16 import org.hibernate.TransactionException; 17 import org.hibernate.jdbc.JDBCContext; 18 19 25 public class JDBCTransaction implements Transaction { 26 27 private static final Log log = LogFactory.getLog(JDBCTransaction.class); 28 29 private final JDBCContext jdbcContext; 30 private final TransactionFactory.Context transactionContext; 31 32 private boolean toggleAutoCommit; 33 private boolean rolledBack; 34 private boolean committed; 35 private boolean begun; 36 private boolean commitFailed; 37 private List synchronizations; 38 private boolean callback; 39 40 public JDBCTransaction(JDBCContext jdbcContext, TransactionFactory.Context transactionContext) { 41 this.jdbcContext = jdbcContext; 42 this.transactionContext = transactionContext; 43 } 44 45 public void begin() throws HibernateException { 46 log.debug("begin"); 47 48 try { 49 toggleAutoCommit = jdbcContext.connection().getAutoCommit(); 50 if ( log.isDebugEnabled() ) log.debug("current autocommit status: " + toggleAutoCommit); 51 if (toggleAutoCommit) { 52 log.debug("disabling autocommit"); 53 jdbcContext.connection().setAutoCommit(false); 54 } 55 } 56 catch (SQLException e) { 57 log.error("JDBC begin failed", e); 58 throw new TransactionException("JDBC begin failed: ", e); 59 } 60 61 callback = jdbcContext.registerCallbackIfNecessary(); 62 63 begun = true; 64 } 65 66 private void closeIfRequired() throws HibernateException { 67 if ( callback && transactionContext.shouldAutoClose() && transactionContext.isOpen() ) { 68 try { 69 transactionContext.managedClose(); 70 } 71 catch (HibernateException he) { 72 log.error("Could not close session", he); 73 } 75 } 76 } 77 78 public void commit() throws HibernateException { 79 if (!begun) { 80 throw new TransactionException("Transaction not successfully started"); 81 } 82 83 log.debug("commit"); 84 85 if ( !transactionContext.isFlushModeNever() && callback ) { 86 transactionContext.managedFlush(); } 88 89 beforeTransactionCompletion(); 90 if ( callback ) { 91 jdbcContext.beforeTransactionCompletion( this ); 92 } 93 94 try { 95 commitAndResetAutoCommit(); 96 log.debug("committed JDBC Connection"); 97 committed = true; 98 if ( callback ) { 99 jdbcContext.afterTransactionCompletion( true, this ); 100 } 101 afterTransactionCompletion( Status.STATUS_COMMITTED ); 102 } 103 catch (SQLException e) { 104 log.error("JDBC commit failed", e); 105 commitFailed = true; 106 if ( callback ) { 107 jdbcContext.afterTransactionCompletion( false, this ); 108 } 109 afterTransactionCompletion( Status.STATUS_UNKNOWN ); 110 throw new TransactionException("JDBC commit failed", e); 111 } 112 finally { 113 closeIfRequired(); 114 } 115 } 116 117 private void commitAndResetAutoCommit() throws SQLException { 118 try { 119 jdbcContext.connection().commit(); 120 } 121 finally { 122 toggleAutoCommit(); 123 } 124 } 125 126 public void rollback() throws HibernateException { 127 128 if (!begun) { 129 throw new TransactionException("Transaction not successfully started"); 130 } 131 132 log.debug("rollback"); 133 134 if (!commitFailed) { 135 136 beforeTransactionCompletion(); 137 if ( callback ) { 138 jdbcContext.beforeTransactionCompletion( this ); 139 } 140 141 try { 142 rollbackAndResetAutoCommit(); 143 log.debug("rolled back JDBC Connection"); 144 rolledBack = true; 145 afterTransactionCompletion(Status.STATUS_ROLLEDBACK); 146 } 147 catch (SQLException e) { 148 log.error("JDBC rollback failed", e); 149 afterTransactionCompletion(Status.STATUS_UNKNOWN); 150 throw new TransactionException("JDBC rollback failed", e); 151 } 152 finally { 153 if ( callback ) { 154 jdbcContext.afterTransactionCompletion( false, this ); 155 } 156 closeIfRequired(); 157 } 158 } 159 } 160 161 private void rollbackAndResetAutoCommit() throws SQLException { 162 try { 163 jdbcContext.connection().rollback(); 164 } 165 finally { 166 toggleAutoCommit(); 167 } 168 } 169 170 private void toggleAutoCommit() { 171 try { 172 if (toggleAutoCommit) { 173 log.debug("re-enabling autocommit"); 174 jdbcContext.connection().setAutoCommit( true ); 175 } 176 } 177 catch (Exception sqle) { 178 log.error("Could not toggle autocommit", sqle); 179 } 181 } 182 183 public boolean wasRolledBack() { 184 return rolledBack; 185 } 186 187 public boolean wasCommitted() { 188 return committed; 189 } 190 191 public boolean isActive() { 192 return begun && ! ( rolledBack || committed | commitFailed ); 193 } 194 195 public void registerSynchronization(Synchronization sync) throws HibernateException { 196 if (sync==null) throw new NullPointerException ("null Synchronization"); 197 if (synchronizations==null) { 198 synchronizations = new ArrayList (); 199 } 200 synchronizations.add(sync); 201 } 202 203 private void beforeTransactionCompletion() { 204 if (synchronizations!=null) { 205 for ( int i=0; i<synchronizations.size(); i++ ) { 206 Synchronization sync = (Synchronization ) synchronizations.get(i); 207 try { 208 sync.beforeCompletion(); 209 } 210 catch (Throwable t) { 211 log.error("exception calling user Synchronization", t); 212 } 213 } 214 } 215 } 216 217 private void afterTransactionCompletion(int status) { 218 if (synchronizations!=null) { 219 for ( int i=0; i<synchronizations.size(); i++ ) { 220 Synchronization sync = (Synchronization ) synchronizations.get(i); 221 try { 222 sync.afterCompletion(status); 223 } 224 catch (Throwable t) { 225 log.error("exception calling user Synchronization", t); 226 } 227 } 228 } 229 } 230 } 231 | Popular Tags |