chenying99

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

hibernate 也一样,

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

 

SessionImpl 里有一个方法 connection()

 

Java代码  收藏代码
  1. public Connection connection() throws HibernateException {  
  2.     errorIfClosed();  
  3.     return jdbcContext.borrowConnection();  
  4. }  

 

 Session 取得 Connection, 是委托 jdbcContext 。

 看下 jdbcContext.borrowConnection();

Java代码  收藏代码
  1. public Connection borrowConnection() {  
  2.     return connectionManager.borrowConnection();  
  3. }  

 

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

那我们在看下ConnectionManager,

Java代码  收藏代码
  1. public Connection borrowConnection() {  
  2.     if ( isClosed ) {  
  3.         throw new HibernateException( "connection manager has been closed" );  
  4.     }  
  5.     if ( isSuppliedConnection() ) {  
  6.         return connection;  
  7.     }  
  8.     else {  
  9.         if ( borrowedConnection == null ) {  
  10.             borrowedConnection = BorrowedConnectionProxy.generateProxy( this );  
  11.         }  
  12.         return borrowedConnection;  
  13.     }  
  14. }  

 

ConnectionManager

 

Java代码  收藏代码
  1. private void openConnection() throws HibernateException {  
  2.     if ( connection != null ) {  
  3.         return;  
  4.     }  
  5.   
  6.     log.debug("opening JDBC connection");  
  7.     try {  
  8.         connection = factory.getConnectionProvider().getConnection();  
  9.     }  
  10.     catch (SQLException sqle) {  
  11.         throw JDBCExceptionHelper.convert(  
  12.                 factory.getSQLExceptionConverter(),  
  13.                 sqle,  
  14.                 "Cannot open connection"  
  15.             );  
  16.     }  
  17.   
  18.     callback.connectionOpened(); // register synch; stats.connect()  
  19. }  

 

 关键一句

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

 

这个factory是从哪来的呢?

 

Java代码  收藏代码
  1. new ConnectionManager(  
  2.           owner.getFactory(),  
  3.           this,  
  4.           owner.getConnectionReleaseMode(),  
  5.           connection,  
  6.           interceptor  
  7.    );  

  

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

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

那么看看SessionImpl 的 factory ,

 

Java代码  收藏代码
  1. SessionImpl(  
  2.    final Connection connection,  
  3.    final SessionFactoryImpl factory,  
  4.    final boolean autoclose,  
  5.    final long timestamp,  
  6.    final Interceptor interceptor,  
  7.    final EntityMode entityMode,  
  8.    final boolean flushBeforeCompletionEnabled,  
  9.    final boolean autoCloseSessionEnabled,  
  10.    final ConnectionReleaseMode connectionReleaseMode) {  
  11.   super( factory );  
  12.   
  13.    

 

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

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

 

Java代码  收藏代码
  1. private SessionImpl openSession(  
  2.     Connection connection,  
  3.     boolean autoClose,  
  4.     long timestamp,  
  5.     Interceptor sessionLocalInterceptor  
  6. ) {  
  7.     return new SessionImpl(  
  8.             connection,  
  9.             <span style="color: #ff0000;">this</span>,  
  10.             autoClose,  
  11.             timestamp,  
  12.             sessionLocalInterceptor == null ? interceptor : sessionLocalInterceptor,  
  13.             settings.getDefaultEntityMode(),  
  14.             settings.isFlushBeforeCompletionEnabled(),  
  15.             settings.isAutoCloseSessionEnabled(),  
  16.             settings.getConnectionReleaseMode()  
  17.         );  
  18. }  

 

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

ConnectionManager 里的  factory 就是 SessionFactoryImpl,

factory 找到了,再看看取 ConnectionProvider,

 

ConnectionManager

 

Java代码  收藏代码
  1. factory.getConnectionProvider().getConnection();  

 

要从 factory 中取一个 ConnectionProvider,

 

SessionFactory

 

Java代码  收藏代码
  1. public ConnectionProvider getConnectionProvider() {  
  2.     return settings.getConnectionProvider();  
  3. }  

 

Settings

Java代码  收藏代码
  1. public ConnectionProvider getConnectionProvider() {  
  2.     return connectionProvider;  
  3. }  

 

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

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

 

Configuration

Java代码  收藏代码
  1. Settings settings = buildSettings( copy );  

 

Java代码  收藏代码
  1. public Settings buildSettings(Properties props) throws HibernateException {  
  2.     return settingsFactory.buildSettings( props );  
  3. }  

 

SettingsFactory

 

Java代码  收藏代码
  1. public Settings buildSettings(Properties props) {  
  2.     Settings settings = new Settings();  
  3.       
  4.     //SessionFactory name:  
  5.       
  6.     String sessionFactoryName = props.getProperty(Environment.SESSION_FACTORY_NAME);  
  7.     settings.setSessionFactoryName(sessionFactoryName);  
  8.   
  9.     //JDBC and connection settings:  
  10.   
  11.     ConnectionProvider connections = createConnectionProvider(props);  
  12.     settings.setConnectionProvider(connections);  

 

Java代码  收藏代码
  1. protected ConnectionProvider createConnectionProvider(Properties properties) {  
  2.     return ConnectionProviderFactory.newConnectionProvider(properties);  
  3. }  

 

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

构造了 Settings 里边的 ConnectionProvider,

 

我们看一下具体实现,

Java代码  收藏代码
  1. public static ConnectionProvider newConnectionProvider(Properties properties, Map connectionProviderInjectionData) throws HibernateException {  
  2.     ConnectionProvider connections;  
  3.     String providerClass = properties.getProperty(Environment.CONNECTION_PROVIDER);  
  4.     if ( providerClass!=null ) {  
  5.         try {  
  6.             log.info("Initializing connection provider: " + providerClass);  
  7.             <span style="color: #ff0000;">connections = (ConnectionProvider) ReflectHelper.classForName(providerClass).newInstance();  
  8. /span>          }  
  9.         catch ( Exception e ) {  
  10.             log.error( "Could not instantiate connection provider", e );  
  11.             throw new HibernateException("Could not instantiate connection provider: " + providerClass);  
  12.         }  
  13.     }  
  14.     else if ( properties.getProperty(Environment.DATASOURCE)!=null ) {  
  15.         <span style="color: #ff0000;">connections = new DatasourceConnectionProvider();</span>  
  16.     }  
  17.     else if ( properties.getProperty(Environment.URL)!=null ) {  
  18.         <span style="color: #ff0000;">connections = new DriverManagerConnectionProvider();</span>  
  19.     }  
  20.     else {  
  21.         connections = new UserSuppliedConnectionProvider();  
  22.     }  
  23.   
  24.     if ( connectionProviderInjectionData != null && connectionProviderInjectionData.size() != 0 ) {  
  25.         //inject the data  
  26.         try {  
  27.             BeanInfo info = Introspector.getBeanInfo( connections.getClass() );  
  28.             PropertyDescriptor[] descritors = info.getPropertyDescriptors();  
  29.             int size = descritors.length;  
  30.             for (int index = 0 ; index < size ; index++) {  
  31.                 String propertyName = descritors[index].getName();  
  32.                 if ( connectionProviderInjectionData.containsKey( propertyName ) ) {  
  33.                     Method method = descritors[index].getWriteMethod();  
  34.                     method.invoke( connections, new Object[] { connectionProviderInjectionData.get( propertyName ) } );  
  35.                 }  
  36.             }  
  37.         }  
  38.         catch (IntrospectionException e) {  
  39.             throw new HibernateException("Unable to inject objects into the conenction provider", e);  
  40.         }  
  41.         catch (IllegalAccessException e) {  
  42.             throw new HibernateException("Unable to inject objects into the conenction provider", e);  
  43.         }  
  44.         catch (InvocationTargetException e) {  
  45.             throw new HibernateException("Unable to inject objects into the conenction provider", e);  
  46.         }  
  47.     }  
  48.     <span style="color: #ff0000;">connections.configure(properties);</span>  
  49.     return connections;  
  50. }  

 

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

根据配置文件,

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

然后调用 ConnectionProvider 的 Configuration 方法

Java代码  收藏代码
  1. connections.configure(properties);  

一个 ConnectionProvider 就构造完了,

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

 

Java代码  收藏代码
  1. public Connection getConnection() throws SQLException {  
  2.   
  3.     if ( log.isTraceEnabled() ) log.trace( "total checked-out connections: " + checkedOut );  
  4.   
  5.     synchronized (pool) {  
  6.         if ( !pool.isEmpty() ) {  
  7.             int last = pool.size() - 1;  
  8.             if ( log.isTraceEnabled() ) {  
  9.                 log.trace("using pooled JDBC connection, pool size: " + last);  
  10.                 checkedOut++;  
  11.             }  
  12.             Connection pooled = (Connection) pool.remove(last);  
  13.             if (isolation!=null) pooled.setTransactionIsolation( isolation.intValue() );  
  14.             if ( pooled.getAutoCommit()!=autocommit ) pooled.setAutoCommit(autocommit);  
  15.             return pooled;  
  16.         }  
  17.     }  
  18.   
  19.     log.debug("opening new JDBC connection");  
  20.     <span style="color: #ff0000;">Connection conn = DriverManager.getConnection(url, connectionProps);</span>  
  21.     if (isolation!=null) conn.setTransactionIsolation( isolation.intValue() );  
  22.     if ( conn.getAutoCommit()!=autocommit ) conn.setAutoCommit(autocommit);  
  23.   
  24.     if ( log.isDebugEnabled() ) {  
  25.         log.debug( "created connection to: " + url + ", Isolation Level: " + conn.getTransactionIsolation() );  
  26.     }  
  27.     if ( log.isTraceEnabled() ) checkedOut++;  
  28.   
  29.     return conn;  
  30. }  

 

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

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

分类:

技术点:

相关文章: