现在的位置: 首页 > 综合 > 正文

Hibernate源码解读–DialectResolver源码解读

2012年10月10日 ⁄ 综合 ⁄ 共 4504字 ⁄ 字号 评论关闭

转载http://blog.163.com/among_1985/blog/static/2750052320126178159568/  

概述

我们都知道Hibernate可以支持多种数据库,这种支持是通过对于不同数据库,配置对应数据库的方言完成的。
在早期的Hibernate中,需要通过配置hibernate.dialect参数,指定当前使用的数据库方言。
对于需要同时支持多种数据库的产品来说,每切换一个数据库,就要重新配置以下dialect参数会显得很麻烦。
于是,DialectResolver工厂类就诞生了。
简单的说,DialectResolver以及其子类的作用,是根据数据库的MetaData,完成对于数据库类型的解析。
实际上,DialectResolver的作用还远不止这些,我们使用hibernate时,甚至编写属于自己的DialectResolver接口的实现类,完成我们自定义的dialect的创建。
DialectResolver类结构
DialectResolver使用我们熟知的Conposite、Template Method模式,类结构如下:
Hibernate源码解读--DialectResolver源码解读 - among_1985 - 我的梦想家园

 

上述类图涉及以下几个类:
  • DialectResolverSet:封装一个DialectResolver的集合,hibernate上下文最终使用这个类进行数据库方言解析
  • AbstractDialectResolver:抽象的DialectResolver类,作用是将调用DatabaseMetaData时可能出现的SQLException转换为以Hibernate为基类的运行时异常。
  • StandardDialectResolver:标准的DialectResolver,用来封装hibernate自带的方言解析流程
  • BasicDialectResolver:这个类没什么实际用途,目前代码中,没有对其的任何引用,应该是可以废弃的类
StandardDialectResolver
StandardDialectResolver类中,根据数据库的DatabaseMetaData,找到对应的数据库方言实现类,源码如下:

protected Dialect resolveDialectInternal(DatabaseMetaData metaData) throws SQLException {
String databaseName = metaData.getDatabaseProductName();
int databaseMajorVersion = metaData.getDatabaseMajorVersion();

if ( "CUBRID".equalsIgnoreCase( databaseName ) ) {
return new CUBRIDDialect();
}

if ( "HSQL Database Engine".equals( databaseName ) ) {
return new HSQLDialect();
}

if ( "H2".equals( databaseName ) ) {
return new H2Dialect();
}

if ( "MySQL".equals( databaseName ) ) {
return new MySQLDialect();
}

if ( "PostgreSQL".equals( databaseName ) ) {
final int databaseMinorVersion = metaData.getDatabaseMinorVersion();
if (databaseMajorVersion >= 8 && databaseMinorVersion >= 2) {
return new PostgreSQL82Dialect();
}
return new PostgreSQL81Dialect();
}

if ( "Apache Derby".equals( databaseName ) ) {
final int databaseMinorVersion = metaData.getDatabaseMinorVersion();
if ( databaseMajorVersion > 10 || ( databaseMajorVersion == 10 && databaseMinorVersion >= 7 ) ) {
return new DerbyTenSevenDialect();
}
else if ( databaseMajorVersion == 10 && databaseMinorVersion == 6 ) {
return new DerbyTenSixDialect();
}
else if ( databaseMajorVersion == 10 && databaseMinorVersion == 5 ) {
return new DerbyTenFiveDialect();
}
else {
return new DerbyDialect();
}
}

if ( "ingres".equalsIgnoreCase( databaseName ) ) {
switch( databaseMajorVersion ) {
case 9:
int databaseMinorVersion = metaData.getDatabaseMinorVersion();
if (databaseMinorVersion > 2) {
return new Ingres9Dialect();
}
return new IngresDialect();
case 10:
return new Ingres10Dialect();
default:
LOG.unknownIngresVersion(databaseMajorVersion);
}
return new IngresDialect();
}

if ( databaseName.startsWith( "Microsoft SQL Server" ) ) {
switch ( databaseMajorVersion ) {
case 8:
return new SQLServerDialect();
case 9:
return new SQLServer2005Dialect();
case 10:
return new SQLServer2008Dialect();
default:
LOG.unknownSqlServerVersion(databaseMajorVersion);
}
return new SQLServerDialect();
}

if ( "Sybase SQL Server".equals( databaseName ) || "Adaptive Server Enterprise".equals( databaseName ) ) {
return new SybaseASE15Dialect();
}

if ( databaseName.startsWith( "Adaptive Server Anywhere" ) ) {
return new SybaseAnywhereDialect();
}

if ( "Informix Dynamic Server".equals( databaseName ) ) {
return new InformixDialect();
}

if ( databaseName.equals("DB2 UDB for AS/400" ) ) {
return new DB2400Dialect();
}

if ( databaseName.startsWith( "DB2/" ) ) {
return new DB2Dialect();
}

if ( "Oracle".equals( databaseName ) ) {
switch ( databaseMajorVersion ) {
case 11:
return new Oracle10gDialect();
case 10:
return new Oracle10gDialect();
case 9:
return new Oracle9iDialect();
case 8:
return new Oracle8iDialect();
default:
LOG.unknownOracleVersion(databaseMajorVersion);
}
}

return null;
}

DialectResolverInitiator

DialectResovler最终由DialectResolverInitiator进行初始化。DialectResolverInitiator实现了BasicServiceInitiator接口,完成系统启动时必须的初始化工作。
如果需要配置自定义的DialectResovler对象,只要声明hibernate.dialect_resolvers参数,参数值是以逗号分隔的DialectResovler自定义实现的类名全称。
DialectResolverInitiator初始化并创建DialectResovler对象的源码如下:

private List<DialectResolver> determineResolvers(Map configurationValues, ServiceRegistryImplementor registry) {
final List<DialectResolver> resolvers = new ArrayList<DialectResolver>();

final String resolverImplNames = (String) configurationValues.get( AvailableSettings.DIALECT_RESOLVERS );

if ( StringHelper.isNotEmpty( resolverImplNames ) ) {
final ClassLoaderService classLoaderService = registry.getService( ClassLoaderService.class );
for ( String resolverImplName : StringHelper.split( ", \n\r\f\t", resolverImplNames ) ) {
try {
resolvers.add( (DialectResolver) classLoaderService.classForName( resolverImplName ).newInstance() );
}
catch (HibernateException e) {
throw e;
}
catch (Exception e) {
throw new ServiceException( "Unable to instantiate named dialect resolver [" + resolverImplName + "]", e );
}
}
}
/* 

* 不论是否配置AvailableSettings.DIALECT_RESOLVERS参数,均可以使用StandardDialectResolver进行方言解析

* 因为自定义的DialectResolver处于list的前面,所以自定义的DialectResolver优先级会比系统默认的高

*/

resolvers.add( new StandardDialectResolver() );
return resolvers;
}

抱歉!评论已关闭.