hibernate3 源码阅读 (三) Connection

用 jdbc 操作数据库,是围绕 Connection 这个类 进行的,

hibernate 也一样,

这篇我们围绕 Connection, 看看hibernate是如何做的。

 

SessionImpl 里有一个方法 connection()

 

public Connection connection() throws HibernateException {
	errorIfClosed();
	return jdbcContext.borrowConnection();
}

 

 Session 取得 Connection, 是委托 jdbcContext 。

 看下 jdbcContext.borrowConnection();

public Connection borrowConnection() {
	return connectionManager.borrowConnection();
}

 

 jdbcContext 取得 Connection, 则又要委托 connectionManager,

那我们在看下ConnectionManager,

	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;
		}
	}

 

ConnectionManager

 

	private void openConnection() throws HibernateException {
		if ( connection != null ) {
			return;
		}

		log.debug("opening JDBC connection");
		try {
			connection = factory.getConnectionProvider().getConnection();
		}
		catch (SQLException sqle) {
			throw JDBCExceptionHelper.convert(
					factory.getSQLExceptionConverter(),
					sqle,
					"Cannot open connection"
				);
		}

		callback.connectionOpened(); // register synch; stats.connect()
	}

 

 关键一句

connection = factory.getConnectionProvider().getConnection();

 

这个factory是从哪来的呢?

 

new ConnectionManager(
          owner.getFactory(),
          this,
          owner.getConnectionReleaseMode(),
          connection,
          interceptor
   );

  

是在JdbcContext 初始化时, ConnectionManager 构造函数中作为参数传进来的,

我们已经知道了这个 owner,就是SessionImpl,

那么看看SessionImpl 的 factory ,

 

SessionImpl(
   final Connection connection,
   final SessionFactoryImpl factory,
   final boolean autoclose,
   final long timestamp,
   final Interceptor interceptor,
   final EntityMode entityMode,
   final boolean flushBeforeCompletionEnabled,
   final boolean autoCloseSessionEnabled,
   final ConnectionReleaseMode connectionReleaseMode) {
  super( factory );

 

 

SessionImpl 中的 factory,又是在SessionImpl 构造函数中作为参数传进来的,

那我们再往上一层看,谁初始化的SessionImpl 呢,前边说了,SessionFactory

 

	private SessionImpl openSession(
		Connection connection,
	    boolean autoClose,
	    long timestamp,
	    Interceptor sessionLocalInterceptor
	) {
		return new SessionImpl(
		        connection,
		        this,
		        autoClose,
		        timestamp,
		        sessionLocalInterceptor == null ? interceptor : sessionLocalInterceptor,
		        settings.getDefaultEntityMode(),
		        settings.isFlushBeforeCompletionEnabled(),
		        settings.isAutoCloseSessionEnabled(),
		        settings.getConnectionReleaseMode()
			);
	}

 

看到这个this了吗,就是他,从SessionImpl 传给 JdbcContext 又传个 ConnectionManager ,

ConnectionManager 里的  factory 就是 SessionFactoryImpl,

factory 找到了,再看看取 ConnectionProvider,

 

ConnectionManager

 

  factory.getConnectionProvider().getConnection();

 

要从 factory 中取一个 ConnectionProvider,

 

SessionFactory

 

	public ConnectionProvider getConnectionProvider() {
		return settings.getConnectionProvider();
	}

 

Settings

	public ConnectionProvider getConnectionProvider() {
		return connectionProvider;
	}

 

  原来这个ConnectionProvider 最终是放在 Settings 里边的,

 那么我们看一下 settings 的初始化 看看 settings 是怎么构造出 ConnectionProvider 的,

 

Configuration

 Settings settings = buildSettings( copy );
 

 

	public Settings buildSettings(Properties props) throws HibernateException {
		return settingsFactory.buildSettings( props );
	}

 

SettingsFactory

 

	
	public Settings buildSettings(Properties props) {
		Settings settings = new Settings();
		
		//SessionFactory name:
		
		String sessionFactoryName = props.getProperty(Environment.SESSION_FACTORY_NAME);
		settings.setSessionFactoryName(sessionFactoryName);

		//JDBC and connection settings:

		ConnectionProvider connections = createConnectionProvider(props);
		settings.setConnectionProvider(connections);

 

	protected ConnectionProvider createConnectionProvider(Properties properties) {
		return ConnectionProviderFactory.newConnectionProvider(properties);
	}

 

可以看到,hibernate 通过 ConnectionProviderFactory 类,以hibernate配置文件 (properties) 做参数,

构造了 Settings 里边的 ConnectionProvider,

 

我们看一下具体实现,

	public static ConnectionProvider newConnectionProvider(Properties properties, Map connectionProviderInjectionData) throws HibernateException {
		ConnectionProvider connections;
		String providerClass = properties.getProperty(Environment.CONNECTION_PROVIDER);
		if ( providerClass!=null ) {
			try {
				log.info("Initializing connection provider: " + providerClass);
				connections = (ConnectionProvider) ReflectHelper.classForName(providerClass).newInstance();
			}
			catch ( Exception e ) {
				log.error( "Could not instantiate connection provider", e );
				throw new HibernateException("Could not instantiate connection provider: " + providerClass);
			}
		}
		else if ( properties.getProperty(Environment.DATASOURCE)!=null ) {
			connections = new DatasourceConnectionProvider();
		}
		else if ( properties.getProperty(Environment.URL)!=null ) {
			connections = new DriverManagerConnectionProvider();
		}
		else {
			connections = new UserSuppliedConnectionProvider();
		}

		if ( connectionProviderInjectionData != null && connectionProviderInjectionData.size() != 0 ) {
			//inject the data
			try {
				BeanInfo info = Introspector.getBeanInfo( connections.getClass() );
				PropertyDescriptor[] descritors = info.getPropertyDescriptors();
				int size = descritors.length;
				for (int index = 0 ; index < size ; index++) {
					String propertyName = descritors[index].getName();
					if ( connectionProviderInjectionData.containsKey( propertyName ) ) {
						Method method = descritors[index].getWriteMethod();
						method.invoke( connections, new Object[] { connectionProviderInjectionData.get( propertyName ) } );
					}
				}
			}
			catch (IntrospectionException e) {
				throw new HibernateException("Unable to inject objects into the conenction provider", e);
			}
			catch (IllegalAccessException e) {
				throw new HibernateException("Unable to inject objects into the conenction provider", e);
			}
			catch (InvocationTargetException e) {
				throw new HibernateException("Unable to inject objects into the conenction provider", e);
			}
		}
		connections.configure(properties);
		return connections;
	}

 

好了,我们终于找到了 ConnectionProvider构造的具体实现细节,

根据配置文件,

先判断具体类型,是DatasourceConnectionProvider,DriverManagerConnectionProvider 或是其他,

然后调用 ConnectionProvider 的 Configuration 方法

connections.configure(properties);

一个 ConnectionProvider 就构造完了,

有了ConnectionProvider,就可以通过他的 getConnection 方法,得到我们要的Connection,

 

	public Connection getConnection() throws SQLException {

		if ( log.isTraceEnabled() ) log.trace( "total checked-out connections: " + checkedOut );

		synchronized (pool) {
			if ( !pool.isEmpty() ) {
				int last = pool.size() - 1;
				if ( log.isTraceEnabled() ) {
					log.trace("using pooled JDBC connection, pool size: " + last);
					checkedOut++;
				}
				Connection pooled = (Connection) pool.remove(last);
				if (isolation!=null) pooled.setTransactionIsolation( isolation.intValue() );
				if ( pooled.getAutoCommit()!=autocommit ) pooled.setAutoCommit(autocommit);
				return pooled;
			}
		}

		log.debug("opening new JDBC connection");
		Connection conn = DriverManager.getConnection(url, connectionProps);
		if (isolation!=null) conn.setTransactionIsolation( isolation.intValue() );
		if ( conn.getAutoCommit()!=autocommit ) conn.setAutoCommit(autocommit);

		if ( log.isDebugEnabled() ) {
			log.debug( "created connection to: " + url + ", Isolation Level: " + conn.getTransactionIsolation() );
		}
		if ( log.isTraceEnabled() ) checkedOut++;

		return conn;
	}

 

 Connection conn = DriverManager.getConnection(url, connectionProps);

至此,我们就把 hibernate 中 关于Connection的构造以及调用 大概看了一遍。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值