關于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; } }
浙公網安備 33010602011771號