日期:2014-05-16  浏览次数:20527 次

ConnectionManager 管理JDBC连接
log:打印日志(废话)
callback: 回调类:在 打开连接,关闭连接,事务状态时机定义动作
factory:供应ConnectionProvider以提供连接,Batch以管理Statement
releaseMode:释放模式
connection:连接缓存
borrowedConnection:连用连接缓存
wasConnectionSupplied:提供的连接是被客户端提供的而非ConnectionProvider
batcher:管理Statement
interceptor:拦截器,给batcher用
isClosed:该类实例是否关闭
isFlushing:改状态值是为了解决一次flush中发多条Statement时,重复释放连接问题


 可以把session与connection的使用关系分为三种 

  session使用的连接是被提供的,常常SessionFactory.openSession(connection,Interceptor?) 
  session使用的连接被借给客户端,常常session.connection 
  session通过connectionProvider.getConnection得到的连接 
   如果session使用的连接是被提供的,那么当之后调用session.connection向session借取的连接就是之前被提供的连接,这类型的连接释放模式必须是ON_CLOSE,但即使这样,连接也不能由session关闭之后而关闭,既然是被提供的,当然生命周期不必与Session同步 
   如果session使用的连接是通过connectionprovider得到,并被提供给客户端,那么此时的客户端得到的是一个代理连接(被代理的对象正是connectionprovider获取的),当调用代理连接的close方法,并不能关闭被代理的连接,只是标识缓存中的borrowedConnection为空并设置代理连接不可用,因为既然是借用session的,当然不能够擅自了结连接。 
   如果session使用的连接是通过connectionprovider得到,那么连接的释放遵守ConnectionReleaseMode定义

  释放操作执行

   如果调用batch批量关闭,则设置releasing=true,批量关闭完成之后设置为false,对于每条Statement的关闭,总是检查如果releasing!=true(显然不成立),不会执行afterStatement,场景
     事务环境的事务完成后调用
     非事务环境查询
     session.close 
    session.disconnect
   如果非批量关闭,对于每条Statement,显然总是执行afterStatement;
   调用afterStatement并不能保证连接立即关闭,下列条件都必须满足
      releaseMode等于AFTER_STATEMENT或者非事务环境下的自动提交模式
      flushing=false 在session.flush或执行自动刷新时(比如FlushMode.ALWAYS),执行flushBeginning时flushing 设置为 true;尚未flush完成即没执行flushEnding(设置flushing=false)不行,必须执行完flushEnding
      由batch管理的Statement和ResultSet全被关闭掉
      连接没被借出去或被借出去之后关闭掉的 
   当事务完成之后或非事务查询时都会调用afterTransaction,以下条件之一满足即可关闭连接
       releaseMode等于AFTER_TRANSACTION
      releaseMode等于AFTER_STATEMENT并且batch还有未关闭的Statement和ResultSet:同时关闭尚未处理的Statement和ResultSet

// $Id: ConnectionManager.java 11304 2007-03-19 22:06:45Z 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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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 Log log = LogFactory.getLog( 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;
		t