哪个 jar 部署了 Hibernate 5.1 class org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl?
Which jar deploys Hibernate 5.1 class org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl?
我正在尝试配置 JBoss AS 7.1.3 以支持 Hibernate 5.1.10.Final,因为此版本修复了一个错误在我的申请中。目前不可能(请不要坚持)升级到WildFly。
为版本 5.1.10.Final 创建了一个新的 JBoss 模块,如下所示:
<module xmlns="urn:jboss:module:1.1" name="org.hibernate" slot="5.1.10.Final">
<resources>
<resource-root path="hibernate-core-5.1.10.Final.jar"/>
<resource-root path="hibernate-entitymanager-5.1.10.Final.jar"/>
<resource-root path="hibernate-infinispan-5.1.10.Final.jar"/>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="asm.asm"/>
<module name="javax.api"/>
<module name="javax.persistence.api"/>
<module name="javax.transaction.api"/>
<module name="javax.validation.api"/>
<module name="org.antlr"/>
<module name="org.apache.commons.collections"/>
<module name="org.dom4j"/>
<module name="org.infinispan" optional="true"/>
<module name="org.javassist"/>
<module name="org.jboss.as.jpa.hibernate" slot="5" optional="true"/>
<module name="org.jboss.logging"/>
<module name="org.hibernate.envers" services="import" optional="true"/>
<module name="org.hibernate.commons-annotations"/>
</dependencies>
</module>
persistence.xml
配置为使用5.1.10.Final版本,如下图:
<persistence-unit name="myunit" transaction-type="JTA">
<jta-data-source>java:jboss/env/jdbc/SCA</jta-data-source>
<!-- Many occurences of <class/> -->
<class>...</class>
<properties>
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect" />
<property name="jboss.as.jpa.providerModule" value="org.hibernate:5.1.10.Final"/>
</properties>
</persistence-unit>
而我的pom.xml
也被配置为依赖5.1.10.Final版本,如下图:
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.1.10.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.1.10.Final</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
</dependency>
</dependencies>
应用程序被部署为使用 5.1.10.Final 版本感谢文件 jboss-deployment-structure.xml
如下:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<deployment>
<exclusions>
<module name="org.hibernate" slot="main" />
</exclusions>
<dependencies>
<module name="org.hibernate" slot="5.1.10.Final" />
</dependencies>
</deployment>
</jboss-deployment-structure>
之后,我可以将我的应用程序部署到 JBoss,但在加载期间我收到以下错误:
11:31:29,815 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 51) MSC00001: Failed to start service jboss.persistenceunit."sca.war#sca": org.jboss.msc.service.StartException in service jboss.persistenceunit."sca.war#sca": javax.persistence.PersistenceException: [PersistenceUnit: sca] Unable to build EntityManagerFactory
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.run(PersistenceUnitServiceImpl.java:100) [jboss-as-jpa-7.1.3.Final.jar:7.1.3.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_79]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_79]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_79]
at org.jboss.threads.JBossThread.run(JBossThread.java:122) [jboss-threads-2.0.0.GA.jar:2.0.0.GA]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: sca] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:915)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:890)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:74)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.createContainerEntityManagerFactory(PersistenceUnitServiceImpl.java:197) [jboss-as-jpa-7.1.3.Final.jar:7.1.3.Final]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.access0(PersistenceUnitServiceImpl.java:57) [jboss-as-jpa-7.1.3.Final.jar:7.1.3.Final]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.run(PersistenceUnitServiceImpl.java:96) [jboss-as-jpa-7.1.3.Final.jar:7.1.3.Final]
... 4 more
Caused by: org.hibernate.HibernateException: Could not instantiate dialect class
at org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.constructDialect(DialectFactoryImpl.java:82)
at org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:64)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:146)
at org.hibernate.service.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:75)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:159)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:131)
at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:73)
at org.hibernate.cfg.Configuration.buildSettingsInternal(Configuration.java:2279)
at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2275)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1744)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905)
... 9 more
Caused by: java.lang.ClassCastException: org.hibernate.dialect.Oracle12cDialect cannot be cast to org.hibernate.dialect.Dialect
at org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.constructDialect(DialectFactoryImpl.java:73)
... 20 more
考虑到 class org.hibernate.dialect.Oracle12cDialect
是 org.hibernate.dialect.Dialect
的子class(我检查了源代码),在我看来我有一些混合版本问题在这里。转换发生在 org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.constructDialect()
方法中,但我不知道哪个 jar 部署了 class 以更正它的版本。
在你的 conf 中看起来一切都很好。Oracle12cDialect、Dialect 和 DialectFactoryImpl 来自同一个 hibernate-core.jar 所以应该没有这样的问题。
但请检查您的类路径中是否存在多个版本的 hibernate-core。
您可以 运行 maven-duplicate-finder-plugin maven 插件来检查 org.hibernate.dialect.Dialect
是否出现两次:
mvn com.ning.maven.plugins:maven-duplicate-finder-plugin:1.0.9:check
org.hibernate.dialect.Oracle12cDialect cannot be cast to org.hibernate.dialect.Dialect
这是废话,因为Oracle12cDialect 实现了Dialect。但是...
问题
……还有希望!我们在一个层次结构中至少有三个 classloader。
[classloader-base] (without hibernate)
| |
[classloader modul1] [classloader modul2] (with hibernate)
Whearat classloader modul1 和 modul2 加载 hibernate-jars(当然是同一个版本),classloader-base dont!
modul1 和 modul2 有自己的方言界面副本,因此它们不兼容。
如果现在,modul1 在 class 中有一个像这样的字段:
(modul 1)
public Dialect foobarDialect;
但是模块 2 创建的实例是这样的:
(modul 2)
setFoobarDialect(new Oracle12cDialect());
因为 modul1 有自己的方言版本,加载时与 modul2 的方言版本不同,因此不兼容。
问题很简单-shell
让我们做一个小实验:
public static void main(String[] args) throws Exception {
File maven = new File("C:/Users/Guest/.m2/repository/");
String hbm = "org/hibernate/hibernate-core/5.2.1.Final/hibernate-core-5.2.1.Final.jar";
String jpa = "org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar";
String logging = "org/jboss/logging/jboss-logging/3.1.3.GA/jboss-logging-3.1.3.GA.jar";
String jta = "javax/transaction/jta/1.1/jta-1.1.jar";
URL[] urls = new URL[] {
new File(maven, hbm).toURL(),
new File(maven, jpa).toURL(),
new File(maven, logging).toURL(),
new File(maven, jta).toURL()
};
ClassLoader module1 = new URLClassLoader(urls);
ClassLoader module2 = new URLClassLoader(urls);
Class dialect = module1.loadClass("org.hibernate.dialect.Oracle12cDialect");
Class interfac = module2.loadClass("org.hibernate.dialect.Dialect");
System.out.println(interfac.toString());
System.out.println(dialect.toString());
System.out.println(interfac.isAssignableFrom(dialect));
}
将打印:
class org.hibernate.dialect.Dialect
class org.hibernate.dialect.Oracle12cDialect
false <- ah, its incompatible.
如何解决?
您可以通过从与第一个模块相同的 classloader 加载接口来解决 nut-shell。
Class interfac = module1.loadClass("org.hibernate.dialect.Dialect");
...
class org.hibernate.dialect.Dialect
class org.hibernate.dialect.Oracle12cDialect
true <- solved
解决方案
但是JBoss怎么解决呢?只要您不为我们提供对基础架构的完整访问权限,就没有干净的解决方案。这可能会给您带来一些法律问题,请不要提供对项目基础设施的访问。请改用解决方法,直到您可以迁移到 Wildfly。
解决方法
但是有一个简单的解决方法,将hibernate相关的jar复制到JBossjboss/lib/endorsed
.
的endorsed/ext文件夹中
这将为整个 jboss 加载一个休眠模式,任何其他模块都不会覆盖此基本加载。
经过进一步挖掘,我在 WildFly documentation 的页面中发现了一些亮点。
因此,我更改了 persistence.xml
文件中的一行 Hibernate 属性,替换为:
<property name="jboss.as.jpa.providerModule" value="org.hibernate:5.1.10.Final"/>
来自
<property name="org.hibernate.jpa.HibernatePersistenceProvider" value="org.hibernate:5.1.10.Final"/>
这使得 JBoss 加载没有任何错误,并且持久性单元已正确构建。
我正在尝试配置 JBoss AS 7.1.3 以支持 Hibernate 5.1.10.Final,因为此版本修复了一个错误在我的申请中。目前不可能(请不要坚持)升级到WildFly。
为版本 5.1.10.Final 创建了一个新的 JBoss 模块,如下所示:
<module xmlns="urn:jboss:module:1.1" name="org.hibernate" slot="5.1.10.Final">
<resources>
<resource-root path="hibernate-core-5.1.10.Final.jar"/>
<resource-root path="hibernate-entitymanager-5.1.10.Final.jar"/>
<resource-root path="hibernate-infinispan-5.1.10.Final.jar"/>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="asm.asm"/>
<module name="javax.api"/>
<module name="javax.persistence.api"/>
<module name="javax.transaction.api"/>
<module name="javax.validation.api"/>
<module name="org.antlr"/>
<module name="org.apache.commons.collections"/>
<module name="org.dom4j"/>
<module name="org.infinispan" optional="true"/>
<module name="org.javassist"/>
<module name="org.jboss.as.jpa.hibernate" slot="5" optional="true"/>
<module name="org.jboss.logging"/>
<module name="org.hibernate.envers" services="import" optional="true"/>
<module name="org.hibernate.commons-annotations"/>
</dependencies>
</module>
persistence.xml
配置为使用5.1.10.Final版本,如下图:
<persistence-unit name="myunit" transaction-type="JTA">
<jta-data-source>java:jboss/env/jdbc/SCA</jta-data-source>
<!-- Many occurences of <class/> -->
<class>...</class>
<properties>
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect" />
<property name="jboss.as.jpa.providerModule" value="org.hibernate:5.1.10.Final"/>
</properties>
</persistence-unit>
而我的pom.xml
也被配置为依赖5.1.10.Final版本,如下图:
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.1.10.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.1.10.Final</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
</dependency>
</dependencies>
应用程序被部署为使用 5.1.10.Final 版本感谢文件 jboss-deployment-structure.xml
如下:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<deployment>
<exclusions>
<module name="org.hibernate" slot="main" />
</exclusions>
<dependencies>
<module name="org.hibernate" slot="5.1.10.Final" />
</dependencies>
</deployment>
</jboss-deployment-structure>
之后,我可以将我的应用程序部署到 JBoss,但在加载期间我收到以下错误:
11:31:29,815 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 51) MSC00001: Failed to start service jboss.persistenceunit."sca.war#sca": org.jboss.msc.service.StartException in service jboss.persistenceunit."sca.war#sca": javax.persistence.PersistenceException: [PersistenceUnit: sca] Unable to build EntityManagerFactory
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.run(PersistenceUnitServiceImpl.java:100) [jboss-as-jpa-7.1.3.Final.jar:7.1.3.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_79]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_79]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_79]
at org.jboss.threads.JBossThread.run(JBossThread.java:122) [jboss-threads-2.0.0.GA.jar:2.0.0.GA]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: sca] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:915)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:890)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:74)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.createContainerEntityManagerFactory(PersistenceUnitServiceImpl.java:197) [jboss-as-jpa-7.1.3.Final.jar:7.1.3.Final]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.access0(PersistenceUnitServiceImpl.java:57) [jboss-as-jpa-7.1.3.Final.jar:7.1.3.Final]
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl.run(PersistenceUnitServiceImpl.java:96) [jboss-as-jpa-7.1.3.Final.jar:7.1.3.Final]
... 4 more
Caused by: org.hibernate.HibernateException: Could not instantiate dialect class
at org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.constructDialect(DialectFactoryImpl.java:82)
at org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:64)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:146)
at org.hibernate.service.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:75)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:159)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:131)
at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:73)
at org.hibernate.cfg.Configuration.buildSettingsInternal(Configuration.java:2279)
at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2275)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1744)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905)
... 9 more
Caused by: java.lang.ClassCastException: org.hibernate.dialect.Oracle12cDialect cannot be cast to org.hibernate.dialect.Dialect
at org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.constructDialect(DialectFactoryImpl.java:73)
... 20 more
考虑到 class org.hibernate.dialect.Oracle12cDialect
是 org.hibernate.dialect.Dialect
的子class(我检查了源代码),在我看来我有一些混合版本问题在这里。转换发生在 org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.constructDialect()
方法中,但我不知道哪个 jar 部署了 class 以更正它的版本。
在你的 conf 中看起来一切都很好。Oracle12cDialect、Dialect 和 DialectFactoryImpl 来自同一个 hibernate-core.jar 所以应该没有这样的问题。
但请检查您的类路径中是否存在多个版本的 hibernate-core。
您可以 运行 maven-duplicate-finder-plugin maven 插件来检查 org.hibernate.dialect.Dialect
是否出现两次:
mvn com.ning.maven.plugins:maven-duplicate-finder-plugin:1.0.9:check
org.hibernate.dialect.Oracle12cDialect cannot be cast to org.hibernate.dialect.Dialect
这是废话,因为Oracle12cDialect 实现了Dialect。但是...
问题
……还有希望!我们在一个层次结构中至少有三个 classloader。
[classloader-base] (without hibernate)
| |
[classloader modul1] [classloader modul2] (with hibernate)
Whearat classloader modul1 和 modul2 加载 hibernate-jars(当然是同一个版本),classloader-base dont!
modul1 和 modul2 有自己的方言界面副本,因此它们不兼容。
如果现在,modul1 在 class 中有一个像这样的字段:
(modul 1)
public Dialect foobarDialect;
但是模块 2 创建的实例是这样的:
(modul 2)
setFoobarDialect(new Oracle12cDialect());
因为 modul1 有自己的方言版本,加载时与 modul2 的方言版本不同,因此不兼容。
问题很简单-shell
让我们做一个小实验:
public static void main(String[] args) throws Exception {
File maven = new File("C:/Users/Guest/.m2/repository/");
String hbm = "org/hibernate/hibernate-core/5.2.1.Final/hibernate-core-5.2.1.Final.jar";
String jpa = "org/hibernate/javax/persistence/hibernate-jpa-2.0-api/1.0.1.Final/hibernate-jpa-2.0-api-1.0.1.Final.jar";
String logging = "org/jboss/logging/jboss-logging/3.1.3.GA/jboss-logging-3.1.3.GA.jar";
String jta = "javax/transaction/jta/1.1/jta-1.1.jar";
URL[] urls = new URL[] {
new File(maven, hbm).toURL(),
new File(maven, jpa).toURL(),
new File(maven, logging).toURL(),
new File(maven, jta).toURL()
};
ClassLoader module1 = new URLClassLoader(urls);
ClassLoader module2 = new URLClassLoader(urls);
Class dialect = module1.loadClass("org.hibernate.dialect.Oracle12cDialect");
Class interfac = module2.loadClass("org.hibernate.dialect.Dialect");
System.out.println(interfac.toString());
System.out.println(dialect.toString());
System.out.println(interfac.isAssignableFrom(dialect));
}
将打印:
class org.hibernate.dialect.Dialect
class org.hibernate.dialect.Oracle12cDialect
false <- ah, its incompatible.
如何解决?
您可以通过从与第一个模块相同的 classloader 加载接口来解决 nut-shell。
Class interfac = module1.loadClass("org.hibernate.dialect.Dialect");
...
class org.hibernate.dialect.Dialect
class org.hibernate.dialect.Oracle12cDialect
true <- solved
解决方案
但是JBoss怎么解决呢?只要您不为我们提供对基础架构的完整访问权限,就没有干净的解决方案。这可能会给您带来一些法律问题,请不要提供对项目基础设施的访问。请改用解决方法,直到您可以迁移到 Wildfly。
解决方法
但是有一个简单的解决方法,将hibernate相关的jar复制到JBossjboss/lib/endorsed
.
这将为整个 jboss 加载一个休眠模式,任何其他模块都不会覆盖此基本加载。
经过进一步挖掘,我在 WildFly documentation 的页面中发现了一些亮点。
因此,我更改了 persistence.xml
文件中的一行 Hibernate 属性,替换为:
<property name="jboss.as.jpa.providerModule" value="org.hibernate:5.1.10.Final"/>
来自
<property name="org.hibernate.jpa.HibernatePersistenceProvider" value="org.hibernate:5.1.10.Final"/>
这使得 JBoss 加载没有任何错误,并且持久性单元已正确构建。