用 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的构造以及调用 大概看了一遍。