/** * Create a new JDBC 3.0 Savepoint for the current Connection, * using generated savepoint names that are unique for the Connection. * @return the new Savepoint * @throws SQLException if thrown by the JDBC driver */ public Savepoint createSavepoint() throws SQLException { this.savepointCounter++; return getConnection().setSavepoint(SAVEPOINT_NAME_PREFIX + this.savepointCounter); }
/** * Return whether JDBC 3.0 Savepoints are supported. * Caches the flag for the lifetime of this ConnectionHolder. * @throws SQLException if thrown by the JDBC driver */ public boolean supportsSavepoints() throws SQLException { if (this.savepointsSupported == null) { this.savepointsSupported = getConnection().getMetaData().supportsSavepoints(); } return this.savepointsSupported; }
/** * This implementation releases the given JDBC 3.0 Savepoint. * @see java.sql.Connection#releaseSavepoint */ @Override public void releaseSavepoint(Object savepoint) throws TransactionException { ConnectionHolder conHolder = getConnectionHolderForSavepoint(); try { conHolder.getConnection().releaseSavepoint((Savepoint) savepoint); } catch (Throwable ex) { logger.debug("Could not explicitly release JDBC savepoint", ex); } }
/** * Determine whether the given two Connections are equal, asking the target * Connection in case of a proxy. Used to detect equality even if the * user passed in a raw target Connection while the held one is a proxy. * @param conHolder the ConnectionHolder for the held Connection (potentially a proxy) * @param passedInCon the Connection passed-in by the user * (potentially a target Connection without proxy) * @return whether the given Connections are equal * @see #getTargetConnection */ private static boolean connectionEquals(ConnectionHolder conHolder, Connection passedInCon) { if (!conHolder.hasConnection()) { return false; } Connection heldCon = conHolder.getConnection(); // Explicitly check for identity too: for Connection handles that do not implement // "equals" properly, such as the ones Commons DBCP exposes). return (heldCon == passedInCon || heldCon.equals(passedInCon) || getTargetConnection(heldCon).equals(passedInCon)); }
@Override protected void doRollback(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); if (status.isDebug()) { logger.debug("Rolling back JDBC transaction on Connection [" + con + "]"); } try { con.rollback(); } catch (SQLException ex) { throw new TransactionSystemException("Could not roll back JDBC transaction", ex); } }
/** * This implementation rolls back to the given JDBC 3.0 Savepoint. * @see java.sql.Connection#rollback(java.sql.Savepoint) */ @Override public void rollbackToSavepoint(Object savepoint) throws TransactionException { ConnectionHolder conHolder = getConnectionHolderForSavepoint(); try { conHolder.getConnection().rollback((Savepoint) savepoint); conHolder.resetRollbackOnly(); } catch (Throwable ex) { throw new TransactionSystemException("Could not roll back to JDBC savepoint", ex); } }
@Override protected void doCommit(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); if (status.isDebug()) { logger.debug("Committing JDBC transaction on Connection [" + con + "]"); } try { con.commit(); } catch (SQLException ex) { throw new TransactionSystemException("Could not commit JDBC transaction", ex); } }
@Override protected void doSetRollbackOnly(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); if (status.isDebug()) { logger.debug("Setting JDBC transaction [" + txObject.getConnectionHolder().getConnection() + "] rollback-only"); } txObject.setRollbackOnly(); }
@Override public void beforeCompletion() { // Release Connection early if the holder is not open anymore // (that is, not used by another resource like a Hibernate Session // that has its own cleanup via transaction synchronization), // to avoid issues with strict JTA implementations that expect // the close call before transaction completion. if (!this.connectionHolder.isOpen()) { TransactionSynchronizationManager.unbindResource(this.dataSource); this.holderActive = false; if (this.connectionHolder.hasConnection()) { releaseConnection(this.connectionHolder.getConnection(), this.dataSource); } } }
@Override public void suspend() { if (this.holderActive) { TransactionSynchronizationManager.unbindResource(this.dataSource); if (this.connectionHolder.hasConnection() && !this.connectionHolder.isOpen()) { // Release Connection on suspend if the application doesn't keep // a handle to it anymore. We will fetch a fresh Connection if the // application accesses the ConnectionHolder again after resume, // assuming that it will participate in the same transaction. releaseConnection(this.connectionHolder.getConnection(), this.dataSource); this.connectionHolder.setConnection(null); } } }
@Override protected void doCleanupAfterCompletion(Object transaction) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; // Remove the connection holder from the thread, if exposed. if (txObject.isNewConnectionHolder()) { TransactionSynchronizationManager.unbindResource(obtainDataSource()); } // Reset connection. Connection con = txObject.getConnectionHolder().getConnection(); try { if (txObject.isMustRestoreAutoCommit()) { con.setAutoCommit(true); } DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel()); } catch (Throwable ex) { logger.debug("Could not reset JDBC Connection after transaction", ex); } if (txObject.isNewConnectionHolder()) { if (logger.isDebugEnabled()) { logger.debug("Releasing JDBC Connection [" + con + "] after transaction"); } DataSourceUtils.releaseConnection(con, this.dataSource); } txObject.getConnectionHolder().clear(); }
@Override public void afterCompletion(int status) { // If we haven't closed the Connection in beforeCompletion, // close it now. The holder might have been used for other // cleanup in the meantime, for example by a Hibernate Session. if (this.holderActive) { // The thread-bound ConnectionHolder might not be available anymore, // since afterCompletion might get called from a different thread. TransactionSynchronizationManager.unbindResourceIfPossible(this.dataSource); this.holderActive = false; if (this.connectionHolder.hasConnection()) { releaseConnection(this.connectionHolder.getConnection(), this.dataSource); // Reset the ConnectionHolder: It might remain bound to the thread. this.connectionHolder.setConnection(null); } } this.connectionHolder.reset(); } }
con = txObject.getConnectionHolder().getConnection();
conHolder.setConnection(fetchConnection(dataSource)); return conHolder.getConnection();
/** * Create a new JDBC 3.0 Savepoint for the current Connection, * using generated savepoint names that are unique for the Connection. * @return the new Savepoint * @throws SQLException if thrown by the JDBC driver */ public Savepoint createSavepoint() throws SQLException { this.savepointCounter++; return getConnection().setSavepoint(SAVEPOINT_NAME_PREFIX + this.savepointCounter); }
/** * Return whether JDBC 3.0 Savepoints are supported. * Caches the flag for the lifetime of this ConnectionHolder. * @throws SQLException if thrown by the JDBC driver */ public boolean supportsSavepoints() throws SQLException { if (this.savepointsSupported == null) { this.savepointsSupported = new Boolean(getConnection().getMetaData().supportsSavepoints()); } return this.savepointsSupported.booleanValue(); }
/** * This implementation releases the given JDBC 3.0 Savepoint. * @see java.sql.Connection#releaseSavepoint */ public void releaseSavepoint(Object savepoint) throws TransactionException { try { getConnectionHolderForSavepoint().getConnection().releaseSavepoint((Savepoint) savepoint); } catch (Throwable ex) { logger.debug("Could not explicitly release JDBC savepoint", ex); } }
/** * Return whether JDBC 3.0 Savepoints are supported. * Caches the flag for the lifetime of this ConnectionHolder. * @throws SQLException if thrown by the JDBC driver */ public boolean supportsSavepoints() throws SQLException { if (this.savepointsSupported == null) { this.savepointsSupported = getConnection().getMetaData().supportsSavepoints(); } return this.savepointsSupported; }
/** * This implementation rolls back to the given JDBC 3.0 Savepoint. * @see java.sql.Connection#rollback(java.sql.Savepoint) */ public void rollbackToSavepoint(Object savepoint) throws TransactionException { try { getConnectionHolderForSavepoint().getConnection().rollback((Savepoint) savepoint); } catch (Throwable ex) { throw new TransactionSystemException("Could not roll back to JDBC savepoint", ex); } }
@Override protected void doSetRollbackOnly(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); if (status.isDebug()) { logger.debug("Setting JDBC transaction [" + txObject.getConnectionHolder().getConnection() + "] rollback-only"); } txObject.setRollbackOnly(); }