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 datatry {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的构造以及调用 大概看了一遍。
?
<bean id="dataSource" destroy-method="close"><property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /><!--<property name="url" value="jdbc:mysql://localhost:3306/testmysql"/>--><!--<property name="url" value="jdbc:oracle:thin:@localhost:1521:HELL" /> <property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL" /> --> <property name="url" value="jdbc:oracle:thin:@111.111.2.3:1521:FEEL" /> <property name="username" value="grgbanking" /><property name="password" value="passw0rd" /><property name="initialSize" value="3"/><property name="maxIdle" value="2"/><property name="minIdle" value="1"/><property name="maxActive" value="50"/><property name="removeAbandoned" value="true"/><property name="removeAbandonedTimeout" value="180"/><property name="maxWait" value="1000"/></bean><bean id="sessionFactory"name="code">.... 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> } ....上面的代码中 的
Environment.DATASOURCE 如果和 spring 联合起来使用的话 就应该是 其中的 属性dataSource
<bean id="sessionFactory"class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"><property name="dataSource"><ref local="dataSource"/></property><property name="annotatedClasses"> <list> <value>com.dne.framework.security.Role</value> <value>com.dne.framework.security.User</value></list></property><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop><prop key="hibernate.show_sql">true</prop><prop key="hibernate.connection.autocommit">false</prop><prop key="hibernate.connection.release_mode">auto</prop><!-- <prop key="hibernate.hbm2ddl.auto">update</prop> --></props></property> 3 楼 gutou9 2010-07-19 www.uupan.net 网盘资源集散,使用网盘也赚钱