哪个jar部署了Hibernate 5.1类org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl?

时间:2017-09-20 14:56:03

标签: hibernate jboss7.x

我正在尝试将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$1.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.access$500(PersistenceUnitServiceImpl.java:57) [jboss-as-jpa-7.1.3.Final.jar:7.1.3.Final]
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.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

考虑到类org.hibernate.dialect.Oracle12cDialectorg.hibernate.dialect.Dialect的子类(我在源代码中查看过),在我看来,我在这里遇到了一些混合版本的问题。转换发生在org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.constructDialect()方法中,但我不知道哪个jar部署该类以纠正它的版本。

3 个答案:

答案 0 :(得分:0)

你的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

答案 1 :(得分:0)

  

org.hibernate.dialect.Oracle12cDialect无法强制转换为org.hibernate.dialect.Dialect

这是无稽之谈,因为Oracle12cDialect实现了Dialect。但是......

问题

......有希望!我们在层次结构中至少有三个类加载器。

               [classloader-base]                            (without hibernate)
                 |            |
 [classloader modul1]     [classloader modul2]               (with hibernate)

Whearat classloader modul1和modul2加载hibernate-jars(当然在同一版本中),classloader-base dont!

modul1和modul2的Dialect接口的非常自己的副本,所以它们是不兼容的。

如果现在,modul1在类中有一个字段:

       (modul 1)
public Dialect foobarDialect;

但模块2创建了这样的实例:

       (modul 2)
setFoobarDialect(new Oracle12cDialect());

因为modul1有自己的方言版本,与modul2的方言版本的载入不同,不相容。

坚果壳中的问题

让我们做一个小实验:

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.

如何解决?

您可以通过从相同的类加载器加载接口作为第一个模块来解决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复制到JBoss jboss/lib/endorsed的endorsed / ext文件夹中。

这将为完整的jboss加载一个休眠,任何其他模块都不会覆盖此基本负载。

答案 2 :(得分:0)

经过多次挖掘后,我在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加载时没有任何错误,并且持久性单元正确构建。