关于Hibernate的Dialect
org.hibernate HibernateException Dialect must be explicitly set :***
使用Hibernate,有时候会遇到类似上面的异常。
使用代码获取Session是要使用Configuration要调用Configure方法。这个方法很容易被遗忘。
SessionFactory sf=config.configure().buildSessionFactory(); Session session=sf.openSession();
通过API可以知道configure()方法的作用如下:
Use the mappings and properties specified in an application resource named hibernate.cfg.xml
configure()方法默认加载hibernate.cfg.xml文件,使该文件的映射和配置在应用程序中使用;configure()还有重载的方法来指定配置分别是
configure(Document document) configure(File configFile) configure(String resource) configure(URL url)
若使用configure方法那么就可以在hibernate.cfg.xml中配置数据库的dialect:
<property name="dialect">数据库对应的dialect</property>
通过配置来指定数据库对于的的dialect,具体的数据库和数据库对于的dialect如下:
RDBMS | Dialect |
---|---|
DB2 | org.hibernate.dialect.DB2Dialect |
DB2 AS/400 | org.hibernate.dialect.DB2400Dialect |
DB2 OS390 | org.hibernate.dialect.DB2390Dialect |
PostgreSQL | org.hibernate.dialect.PostgreSQLDialect |
MySQL | org.hibernate.dialect.MySQLDialect |
MySQL with InnoDB | org.hibernate.dialect.MySQLInnoDBDialect |
MySQL with MyISAM | org.hibernate.dialect.MySQLMyISAMDialect |
Oracle (any version) | org.hibernate.dialect.OracleDialect |
Oracle 9i/10g | org.hibernate.dialect.Oracle9Dialect |
Sybase | org.hibernate.dialect.SybaseDialect |
Sybase Anywhere | org.hibernate.dialect.SybaseAnywhereDialect |
Microsoft SQL Server | org.hibernate.dialect.SQLServerDialect |
SAP DB | org.hibernate.dialect.SAPDBDialect |
Informix | org.hibernate.dialect.InformixDialect |
HypersonicSQL | org.hibernate.dialect.HSQLDialect |
Ingres | org.hibernate.dialect.IngresDialect |
Progress | org.hibernate.dialect.ProgressDialect |
Mckoi SQL | org.hibernate.dialect.MckoiDialect |
Interbase | org.hibernate.dialect.InterbaseDialect |
Pointbase | org.hibernate.dialect.PointbaseDialect |
FrontBase | org.hibernate.dialect.FrontbaseDialect |
Firebird | org.hibernate.dialect.FirebirdDialect |
使用spring和hibernate时如果使用时,有时候会去掉hibernate.cfg.xml,那么则要在Spring中配置dialect
<property name="hibernateProperties"> <props> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.cache.use_query_cache">false</prop> <prop key="hibernate.format_sql">true</prop> <!-- 配置hibernate.dialect--> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</prop> </props> </property>
通过Hibernate Reference 可以知道,Dialect这部分内容使和数据库的移植性有相关的,在3.2之前的版本,Hibernate是要求用户明确指定数据库的Dialect的,3.2或以上版本通过java.sql.DataBaseMetaData来确定数据库;不过该文档同时指出来这种方法局限于Hibernate已知的数据库且无法进行配置和覆盖。3.3以后,用户可以通过重写org.hibernate.resolver.DialectResolver的resolveDialect方法来自定义方言,“要注册一个或多个解析者,只要用 'hibernate.dialect_resolvers' 配置设置指定它们(由逗号、制表符或空格隔开)就可以了(请参考 org.hibernate.cfg.Environment 上的 DIALECT_RESOLVERS)”。
用户定义的类通过AvailableSettings.DIALECT_RESOLVERS 获取类名,然后通过反射来注册DialectResolver。AvailableSettings.DIALECT_RESOLVERS 配置的类在determineResolvers链上先于StandardDialectResolver,所以自定义的解释者更优先处理DatabaseMetaData。
以下使hibernate初始化DialectResolver链的类。
import org.hibernate.HibernateException; import org.hibernate.cfg.AvailableSettings; import org.hibernate.internal.util.StringHelper; import org.hibernate.service.classloading.spi.ClassLoaderService; import org.hibernate.service.spi.ServiceException; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.jdbc.dialect.spi.DialectResolver; import org.hibernate.service.spi.BasicServiceInitiator; /** * Standard initiator for the standard {@link DialectResolver} service * * @author Steve Ebersole */ public class DialectResolverInitiator implements BasicServiceInitiator<DialectResolver> { public static final DialectResolverInitiator INSTANCE = new DialectResolverInitiator(); @Override public Class<DialectResolver> getServiceInitiated() { return DialectResolver.class; } @Override public DialectResolver initiateService(Map configurationValues, ServiceRegistryImplementor registry) { return new DialectResolverSet( determineResolvers( configurationValues, registry ) ); } private List<DialectResolver> determineResolvers(Map configurationValues, ServiceRegistryImplementor registry) { final List<DialectResolver> resolvers = new ArrayList (); 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 ); } } } resolvers.add( new StandardDialectResolver() ); return resolvers; } }