hibernate 不得不说的那些事--Connection Provider
ConnectionProvider 在hibernate 3.2.3中有五种实现 ,分别是DatasourceConnectionProvider、C3P0ConnectionProvider、ProxoolConnectionProvider、DriverManagerConnectionProvider、UserSuppliedConnectionProvider。
DatasourceConnectionProvider:使用JNDI注册的数据源,如果要使用它,需配置hibernate.connection.datasource 属性。
C3P0ConnectionProvider:使用了C3P0连接池,如果要使用它,需配置hibernate.c3p0.*属性,
ProxoolConnectionProvider:使用了Proxool连接池,如果要使用它,需配置hibernate.proxool.*属性
DriverManagerConnectionProvider:使用了java.sql.DriverManager,也实现了一个简单的连接池。
UserSuppliedConnectionProvider:ConnectionProvider接口的实现,当请求连接的时候,抛出异常。
hibernate获取Connection Provider的源代码如下:
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.fatal("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.C3P0_MAX_SIZE)!=null ) {
connections = new C3P0ConnectionProvider();
}
else if (
properties.getProperty(Environment.PROXOOL_XML)!=null ||
properties.getProperty(Environment.PROXOOL_PROPERTIES)!=null ||
properties.getProperty(Environment.PROXOOL_EXISTING_POOL)!=null
) {
connections = new ProxoolConnectionProvider();
}
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;
}
从源代码不难看出这么多种Connection Provider的优先顺序 :
自定义Connection Provider >DatasourceConnectionProvider>C3P0ConnectionProvider
> ProxoolConnectionProvider>DriverManagerConnectionProvider>UserSuppliedConnectionProvider
首先hibernate检测hibernate.connection.provider_class是否配置了,如果配置了,则根据该配置对应的类(必须要实现ConnectionProvider接口,含无参构造函数)名实例化。
如果hibernate.connection.provider_class没有配置,则检测hibernate.connection.datasource配置,如果配置了,则使用DatasourceConnectionProvider。
如果hibernate.connection.datasource没有配置,则检测hibernate.c3p0.max_size,如果配置了,则使用C3P0ConnectionProvider。
如果hibernate.c3p0.max_size没有配置,则检测hibernate.proxool.xml、hibernate.proxool.properties、hibernate.proxool.existing_pool的配置,只要其中任何一个配置了,则使用ProxoolConnectionProvider。
如果hibernate.proxool.xml、hibernate.proxool.properties、hibernate.proxool.existing_pool都没有配置,则检测hibernate.connection.url的配置,则使用DriverManagerConnectionProvider。
如果以上没有配置的话,则使用UserSuppliedConnectionProvider(抛出异常),提示需要提供连接。