zoukankan      html  css  js  c++  java
  • 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;
    }

  • 相关阅读:
    oracle 数据库 Cause: java.sql.SQLSyntaxErrorException: ORA-00904: "BODY": 标识符无效
    windows获取所有连接过的无线网密码
    element-ui 组件 el-calendar 农历显示问题
    mysql表复制
    console 打印消息时,可以使用 %c 指定随后的文本样式; %s 可引用参数变量。
    mysql 查询出现 "this is incompatible with sql_mode=only_full_group_by"错误解决方案,以及个人rpm方式重装所遇到的问题备份
    java 关于xlsx(xls) 和 csv 文件的数据解析
    idea websorm 激活码(2020-1-6 实测可用)最新
    mysql 连接查询 转换group_concat, find_in_set
    今天带来compass的使用方式
  • 原文地址:https://www.cnblogs.com/chenying99/p/2709032.html
Copyright © 2011-2022 走看看