📄 connectionmanager.java
字号:
// $Id: ConnectionManager.java 11303 2007-03-19 22:06:14Z steve.ebersole@jboss.com $package org.hibernate.jdbc;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.sql.Connection;import java.sql.SQLException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.hibernate.ConnectionReleaseMode;import org.hibernate.HibernateException;import org.hibernate.Interceptor;import org.hibernate.engine.SessionFactoryImplementor;import org.hibernate.exception.JDBCExceptionHelper;import org.hibernate.util.JDBCExceptionReporter;/** * Encapsulates JDBC Connection management logic needed by Hibernate. * <p/> * The lifecycle is intended to span a logical series of interactions with the * database. Internally, this means the the lifecycle of the Session. * * @author Steve Ebersole */public class ConnectionManager implements Serializable { private static final Logger log = LoggerFactory.getLogger( ConnectionManager.class ); public static interface Callback { public void connectionOpened(); public void connectionCleanedUp(); public boolean isTransactionInProgress(); } private transient SessionFactoryImplementor factory; private final Callback callback; private final ConnectionReleaseMode releaseMode; private transient Connection connection; private transient Connection borrowedConnection; private final boolean wasConnectionSupplied; private transient Batcher batcher; private transient Interceptor interceptor; private boolean isClosed; private transient boolean isFlushing; /** * Constructs a ConnectionManager. * <p/> * This is the form used internally. * * @param factory The SessionFactory. * @param callback An observer for internal state change. * @param releaseMode The mode by which to release JDBC connections. * @param connection An externally supplied connection. */ public ConnectionManager( SessionFactoryImplementor factory, Callback callback, ConnectionReleaseMode releaseMode, Connection connection, Interceptor interceptor) { this.factory = factory; this.callback = callback; this.interceptor = interceptor; this.batcher = factory.getSettings().getBatcherFactory().createBatcher( this, interceptor ); this.connection = connection; wasConnectionSupplied = ( connection != null ); this.releaseMode = wasConnectionSupplied ? ConnectionReleaseMode.ON_CLOSE : releaseMode; } /** * Private constructor used exclusively from custom serialization */ private ConnectionManager( SessionFactoryImplementor factory, Callback callback, ConnectionReleaseMode releaseMode, Interceptor interceptor, boolean wasConnectionSupplied, boolean isClosed) { this.factory = factory; this.callback = callback; this.interceptor = interceptor; this.batcher = factory.getSettings().getBatcherFactory().createBatcher( this, interceptor ); this.wasConnectionSupplied = wasConnectionSupplied; this.isClosed = isClosed; this.releaseMode = wasConnectionSupplied ? ConnectionReleaseMode.ON_CLOSE : releaseMode; } /** * The session factory. * * @return the session factory. */ public SessionFactoryImplementor getFactory() { return factory; } /** * The batcher managed by this ConnectionManager. * * @return The batcher. */ public Batcher getBatcher() { return batcher; } /** * Was the connection being used here supplied by the user? * * @return True if the user supplied the JDBC connection; false otherwise */ public boolean isSuppliedConnection() { return wasConnectionSupplied; } /** * Retrieves the connection currently managed by this ConnectionManager. * <p/> * Note, that we may need to obtain a connection to return here if a * connection has either not yet been obtained (non-UserSuppliedConnectionProvider) * or has previously been aggressively released (if supported in this environment). * * @return The current Connection. * * @throws HibernateException Indicates a connection is currently not * available (we are currently manually disconnected). */ public Connection getConnection() throws HibernateException { if ( isClosed ) { throw new HibernateException( "connection manager has been closed" ); } if ( connection == null ) { openConnection(); } return connection; } public boolean hasBorrowedConnection() { // used from testsuite return borrowedConnection != null; } public Connection borrowConnection() { if ( isClosed ) { throw new HibernateException( "connection manager has been closed" ); } if ( isSuppliedConnection() ) { return connection; } else { if ( borrowedConnection == null ) { borrowedConnection = BorrowedConnectionProxy.generateProxy( this ); } return borrowedConnection; } } public void releaseBorrowedConnection() { if ( borrowedConnection != null ) { try { BorrowedConnectionProxy.renderUnuseable( borrowedConnection ); } finally { borrowedConnection = null; } } } /** * Is the connection considered "auto-commit"? * * @return True if we either do not have a connection, or the connection * really is in auto-commit mode. * * @throws SQLException Can be thrown by the Connection.isAutoCommit() check. */ public boolean isAutoCommit() throws SQLException { return connection == null || connection.isClosed() || connection.getAutoCommit(); } /** * Will connections be released after each statement execution? * <p/> * Connections will be released after each statement if either:<ul> * <li>the defined release-mode is {@link ConnectionReleaseMode#AFTER_STATEMENT}; or * <li>the defined release-mode is {@link ConnectionReleaseMode#AFTER_TRANSACTION} but * we are in auto-commit mode. * <p/> * release-mode = {@link ConnectionReleaseMode#ON_CLOSE} should [b]never[/b] release * a connection. * * @return True if the connections will be released after each statement; false otherwise. */ public boolean isAggressiveRelease() { if ( releaseMode == ConnectionReleaseMode.AFTER_STATEMENT ) { return true; } else if ( releaseMode == ConnectionReleaseMode.AFTER_TRANSACTION ) { boolean inAutoCommitState; try { inAutoCommitState = isAutoCommit()&& !callback.isTransactionInProgress(); } catch( SQLException e ) { // assume we are in an auto-commit state inAutoCommitState = true; } return inAutoCommitState; } return false; } /** * Modified version of {@link #isAggressiveRelease} which does not force a * transaction check. This is solely used from our {@link #afterTransaction} * callback, so no need to do the check; plus it seems to cause problems on * websphere (god i love websphere ;) * </p> * It uses this information to decide if an aggressive release was skipped * do to open resources, and if so forces a release. * * @return True if the connections will be released after each statement; false otherwise. */ private boolean isAggressiveReleaseNoTransactionCheck() { if ( releaseMode == ConnectionReleaseMode.AFTER_STATEMENT ) { return true; } else { boolean inAutoCommitState; try { inAutoCommitState = isAutoCommit(); } catch( SQLException e ) { // assume we are in an auto-commit state inAutoCommitState = true; } return releaseMode == ConnectionReleaseMode.AFTER_TRANSACTION && inAutoCommitState; } } /** * Is this ConnectionManager instance "logically" connected. Meaning * do we either have a cached connection available or do we have the * ability to obtain a connection on demand. * * @return True if logically connected; false otherwise. */ public boolean isCurrentlyConnected() { return wasConnectionSupplied ? connection != null : !isClosed; } /** * To be called after execution of each JDBC statement. Used to * conditionally release the JDBC connection aggressively if * the configured release mode indicates. */ public void afterStatement() { if ( isAggressiveRelease() ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -