1 16 17 package org.springframework.jdbc.datasource; 18 19 import java.sql.Connection ; 20 import java.sql.SQLException ; 21 22 import javax.sql.DataSource ; 23 24 import org.springframework.beans.factory.InitializingBean; 25 import org.springframework.transaction.CannotCreateTransactionException; 26 import org.springframework.transaction.TransactionDefinition; 27 import org.springframework.transaction.TransactionSystemException; 28 import org.springframework.transaction.support.AbstractPlatformTransactionManager; 29 import org.springframework.transaction.support.DefaultTransactionStatus; 30 import org.springframework.transaction.support.TransactionSynchronizationManager; 31 import org.springframework.transaction.support.ResourceTransactionManager; 32 33 95 public class DataSourceTransactionManager extends AbstractPlatformTransactionManager 96 implements ResourceTransactionManager, InitializingBean { 97 98 private DataSource dataSource; 99 100 101 106 public DataSourceTransactionManager() { 107 setNestedTransactionAllowed(true); 108 } 109 110 114 public DataSourceTransactionManager(DataSource dataSource) { 115 this(); 116 setDataSource(dataSource); 117 afterPropertiesSet(); 118 } 119 120 135 public void setDataSource(DataSource dataSource) { 136 if (dataSource instanceof TransactionAwareDataSourceProxy) { 137 this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource(); 141 } 142 else { 143 this.dataSource = dataSource; 144 } 145 } 146 147 150 public DataSource getDataSource() { 151 return this.dataSource; 152 } 153 154 public void afterPropertiesSet() { 155 if (getDataSource() == null) { 156 throw new IllegalArgumentException ("Property 'dataSource' is required"); 157 } 158 } 159 160 161 public Object getResourceFactory() { 162 return getDataSource(); 163 } 164 165 protected Object doGetTransaction() { 166 DataSourceTransactionObject txObject = new DataSourceTransactionObject(); 167 txObject.setSavepointAllowed(isNestedTransactionAllowed()); 168 ConnectionHolder conHolder = 169 (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource); 170 txObject.setConnectionHolder(conHolder, false); 171 return txObject; 172 } 173 174 protected boolean isExistingTransaction(Object transaction) { 175 DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; 176 return (txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive()); 177 } 178 179 182 protected void doBegin(Object transaction, TransactionDefinition definition) { 183 DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; 184 Connection con = null; 185 186 try { 187 if (txObject.getConnectionHolder() == null || 188 txObject.getConnectionHolder().isSynchronizedWithTransaction()) { 189 Connection newCon = this.dataSource.getConnection(); 190 if (logger.isDebugEnabled()) { 191 logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction"); 192 } 193 txObject.setConnectionHolder(new ConnectionHolder(newCon), true); 194 } 195 196 txObject.getConnectionHolder().setSynchronizedWithTransaction(true); 197 con = txObject.getConnectionHolder().getConnection(); 198 199 Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); 200 txObject.setPreviousIsolationLevel(previousIsolationLevel); 201 202 if (con.getAutoCommit()) { 206 txObject.setMustRestoreAutoCommit(true); 207 if (logger.isDebugEnabled()) { 208 logger.debug("Switching JDBC Connection [" + con + "] to manual commit"); 209 } 210 con.setAutoCommit(false); 211 } 212 txObject.getConnectionHolder().setTransactionActive(true); 213 214 int timeout = determineTimeout(definition); 215 if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { 216 txObject.getConnectionHolder().setTimeoutInSeconds(timeout); 217 } 218 219 if (txObject.isNewConnectionHolder()) { 221 TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder()); 222 } 223 } 224 225 catch (SQLException ex) { 226 DataSourceUtils.releaseConnection(con, this.dataSource); 227 throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex); 228 } 229 } 230 231 protected Object doSuspend(Object transaction) { 232 DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; 233 txObject.setConnectionHolder(null); 234 ConnectionHolder conHolder = (ConnectionHolder) 235 TransactionSynchronizationManager.unbindResource(this.dataSource); 236 return conHolder; 237 } 238 239 protected void doResume(Object transaction, Object suspendedResources) { 240 ConnectionHolder conHolder = (ConnectionHolder) suspendedResources; 241 TransactionSynchronizationManager.bindResource(this.dataSource, conHolder); 242 } 243 244 protected void doCommit(DefaultTransactionStatus status) { 245 DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); 246 Connection con = txObject.getConnectionHolder().getConnection(); 247 if (status.isDebug()) { 248 logger.debug("Committing JDBC transaction on Connection [" + con + "]"); 249 } 250 try { 251 con.commit(); 252 } 253 catch (SQLException ex) { 254 throw new TransactionSystemException("Could not commit JDBC transaction", ex); 255 } 256 } 257 258 protected void doRollback(DefaultTransactionStatus status) { 259 DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); 260 Connection con = txObject.getConnectionHolder().getConnection(); 261 if (status.isDebug()) { 262 logger.debug("Rolling back JDBC transaction on Connection [" + con + "]"); 263 } 264 try { 265 con.rollback(); 266 } 267 catch (SQLException ex) { 268 throw new TransactionSystemException("Could not roll back JDBC transaction", ex); 269 } 270 } 271 272 protected void doSetRollbackOnly(DefaultTransactionStatus status) { 273 DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); 274 if (status.isDebug()) { 275 logger.debug("Setting JDBC transaction [" + txObject.getConnectionHolder().getConnection() + 276 "] rollback-only"); 277 } 278 txObject.setRollbackOnly(); 279 } 280 281 protected void doCleanupAfterCompletion(Object transaction) { 282 DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; 283 284 if (txObject.isNewConnectionHolder()) { 286 TransactionSynchronizationManager.unbindResource(this.dataSource); 287 } 288 289 Connection con = txObject.getConnectionHolder().getConnection(); 291 try { 292 if (txObject.isMustRestoreAutoCommit()) { 293 con.setAutoCommit(true); 294 } 295 DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel()); 296 } 297 catch (Throwable ex) { 298 logger.debug("Could not reset JDBC Connection after transaction", ex); 299 } 300 301 if (txObject.isNewConnectionHolder()) { 302 if (logger.isDebugEnabled()) { 303 logger.debug("Releasing JDBC Connection [" + con + "] after transaction"); 304 } 305 DataSourceUtils.releaseConnection(con, this.dataSource); 306 } 307 308 txObject.getConnectionHolder().clear(); 309 } 310 311 312 321 private static class DataSourceTransactionObject extends JdbcTransactionObjectSupport { 322 323 private boolean newConnectionHolder; 324 325 private boolean mustRestoreAutoCommit; 326 327 public void setConnectionHolder(ConnectionHolder connectionHolder, boolean newConnectionHolder) { 328 super.setConnectionHolder(connectionHolder); 329 this.newConnectionHolder = newConnectionHolder; 330 } 331 332 public boolean isNewConnectionHolder() { 333 return newConnectionHolder; 334 } 335 336 public boolean hasTransaction() { 337 return (getConnectionHolder() != null && getConnectionHolder().isTransactionActive()); 338 } 339 340 public void setMustRestoreAutoCommit(boolean mustRestoreAutoCommit) { 341 this.mustRestoreAutoCommit = mustRestoreAutoCommit; 342 } 343 344 public boolean isMustRestoreAutoCommit() { 345 return mustRestoreAutoCommit; 346 } 347 348 public void setRollbackOnly() { 349 getConnectionHolder().setRollbackOnly(); 350 } 351 352 public boolean isRollbackOnly() { 353 return getConnectionHolder().isRollbackOnly(); 354 } 355 } 356 357 } 358 | Popular Tags |