• Hibernate源码解读DialectResolver源码解读


    转载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模式,类结构如下:
     
    上述类图涉及以下几个类:
    • 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;
    }

  • 相关阅读:
    websword-update-notification
    SQL Server2005+、MySQL、Oracle 数据库字典生成工具
    fullcalendar小结
    Oracle 表空间查询
    Oracle正则表达式
    深度学习高性能集群(HPC)提交作业总结
    读《Oracle DBA工作笔记》知识点-获取创建语句
    discuz x3.1 整站搬家换域名攻略
    读《Oracle PLSQL 程序设计第五版》创建包规范和包体
    pls-00329非法引用表结构
  • 原文地址:https://www.cnblogs.com/chenying99/p/2709032.html
Copyright © 2020-2023  润新知