用 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,
- <span style="color: #ff0000;">this</span>,
- 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);
- <span style="color: #ff0000;">connections = (ConnectionProvider) ReflectHelper.classForName(providerClass).newInstance();
- /span> }
- 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 ) {
- <span style="color: #ff0000;">connections = new DatasourceConnectionProvider();</span>
- }
- else if ( properties.getProperty(Environment.URL)!=null ) {
- <span style="color: #ff0000;">connections = new DriverManagerConnectionProvider();</span>
- }
- 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);
- }
- }
- <span style="color: #ff0000;">connections.configure(properties);</span>
- 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");
- <span style="color: #ff0000;">Connection conn = DriverManager.getConnection(url, connectionProps);</span>
- 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的构造以及调用 大概看了一遍。