作者:Walter Chou 出处: http://www.cnitblog.com/walter
最近一段时间,周围有好多朋友在用 spring 2.0 + hibernate 3.1 + MyEclipse6.5 整合开发项目的时候都出现了这个问题。异常的截图如下:
网上找到了很多说法,现对这个问题分析如下:
首先是从代码的角度去看这个问题。查看了MyEclipse的日志文件信息如下:
!MESSAGE 在“Generating Artifacts”期间发生了内部错误。
!STACK 0
org.hibernate.HibernateException: unknown Oracle major version [0]
at org.hibernate.dialect.DialectFactory$1.getDialectClass(DialectFactory.java:135)
at org.hibernate.dialect.DialectFactory.determineDialect(DialectFactory.java:65)
at org.hibernate.dialect.DialectFactory.buildDialect(DialectFactory.java:39)
at org.hibernate.cfg.SettingsFactory.determineDialect(SettingsFactory.java:426)
at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:128)
at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2005)
at com.genuitec.eclipse.hibernate.wizards.MEJDBCMetaDataConfiguration.readFromJDBC(MEJDBCMetaDataConfiguration.java:72)
at com.genuitec.eclipse.hibernate.wizards.GenerateArtifactsJob$7.execute(GenerateArtifactsJob.java:877)
at org.hibernate.console.execution.DefaultExecutionContext.execute(DefaultExecutionContext.java:65)
at org.hibernate.console.ConsoleConfiguration.execute(ConsoleConfiguration.java:91)
at com.genuitec.eclipse.hibernate.wizards.GenerateArtifactsJob.buildConfiguration(GenerateArtifactsJob.java:858)
at com.genuitec.eclipse.hibernate.wizards.GenerateArtifactsJob.run(GenerateArtifactsJob.java:405)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)
发现是HibernateException于是查看相关代码,在 org.hibernate.dialect.DialectFactory 及Dialect等相关类中发现如下:
static
{
MAPPERS = new HashMap();
MAPPERS.put("HSQL Database Engine", new VersionInsensitiveMapper("org.hibernate.dialect.HSQLDialect"));
MAPPERS.put("DB2/NT", new VersionInsensitiveMapper("org.hibernate.dialect.DB2Dialect"));
MAPPERS.put("DB2/LINUX", new VersionInsensitiveMapper("org.hibernate.dialect.DB2Dialect"));
MAPPERS.put("MySQL", new VersionInsensitiveMapper("org.hibernate.dialect.MySQLDialect"));
MAPPERS.put("PostgreSQL", new VersionInsensitiveMapper("org.hibernate.dialect.PostgreSQLDialect"));
MAPPERS.put("Microsoft SQL Server Database", new VersionInsensitiveMapper("org.hibernate.dialect.SQLServerDialect"));
MAPPERS.put("Microsoft SQL Server", new VersionInsensitiveMapper("org.hibernate.dialect.SQLServerDialect"));
MAPPERS.put("Sybase SQL Server", new VersionInsensitiveMapper("org.hibernate.dialect.SybaseDialect"));
MAPPERS.put("Adaptive Server Enterprise", new VersionInsensitiveMapper("org.hibernate.dialect.SybaseDialect"));
MAPPERS.put("Informix Dynamic Server", new VersionInsensitiveMapper("org.hibernate.dialect.InformixDialect"));
MAPPERS.put("Apache Derby", new VersionInsensitiveMapper("org.hibernate.dialect.DerbyDialect"));
MAPPERS.put("Oracle", new DatabaseDialectMapper() {
public String getDialectClass(int majorVersion)
{
switch(majorVersion)
{
case 8: // '\b'
return (DialectFactory.class$org$hibernate$dialect$Oracle8iDialect != null ? DialectFactory.class$org$hibernate$dialect$Oracle8iDialect : (DialectFactory.class$org$hibernate$dialect$Oracle8iDialect = DialectFactory._mthclass$("org.hibernate.dialect.Oracle8iDialect"))).getName();
case 9: // '\t'
return (DialectFactory.class$org$hibernate$dialect$Oracle9iDialect != null ? DialectFactory.class$org$hibernate$dialect$Oracle9iDialect : (DialectFactory.class$org$hibernate$dialect$Oracle9iDialect = DialectFactory._mthclass$("org.hibernate.dialect.Oracle9iDialect"))).getName();
case 10: // '\n'
return (DialectFactory.class$org$hibernate$dialect$Oracle10gDialect != null ? DialectFactory.class$org$hibernate$dialect$Oracle10gDialect : (DialectFactory.class$org$hibernate$dialect$Oracle10gDialect = DialectFactory._mthclass$("org.hibernate.dialect.Oracle10gDialect"))).getName();
}
throw new HibernateException("unknown Oracle major version [" + majorVersion + "]");
}
});
}
以上代码可以很清楚看到此异常被抛出时的定义,尤其是最后一行。那么我们为什么会遇到这个问题呢?
很明显跟hibernate的dialect(方言)配置有关!也就是说它的判断应该是这样的逻辑:
MAPPERS.put(
"Oracle",
new DatabaseDialectMapper() {
public String getDialectClass(int majorVersion) {
switch ( majorVersion ) {
case 8: return Oracle8iDialect.class.getName();
case 9: return Oracle9iDialect.class.getName();
case 10: return Oracle10gDialect.class.getName();
default: throw new HibernateException( "unknown Oracle major version [" + majorVersion + "]" );
}
}
}
);
正好有个项目开发环境用了Oracle 11g。那么也同样遇到了这个问题。
看上面的代码就知道了,只有对10g的支持。
后来经过一番研究发现如果是标准的11g,那么将dataSource相关的xml配置里dialect相关的地方用10g的方言也是可以支持的。配置如下:
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle10gDialect
</prop>
</props>
</property>
注意到版本了吧,如果你用的是Oracle9i那么就改成Oracle9iDialect就可以了。
当然,从上面的代码看造成这个问题不一定只有这一个原因,查看Oracle的jdbc驱动发现也有对org.hibernate.dialect的支持。请使用ojdbc14.jar的驱动,12版的驱动对dialect的支持并不是太好。在有就是可能你在配置数据库联接的时候有操作上的问题。不管怎么说他都是没有找到相匹配的方言造成的。
如果还是没有解决问题可参考我的另一篇文章:
http://www.cnitblog.com/Walter/articles/53127.html