【问题标题】:Which jar deploys Hibernate 5.1 class org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl?哪个 jar 部署了 Hibernate 5.1 类 org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl?
【发布时间】:2017-09-20 14:56:03
【问题描述】:

我正在尝试配置 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>

由于文件jboss-deployment-structure.xml 如下所示,应用程序被部署为使用5.1.10.Final 版本:

<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.Oracle12cDialect 类是 org.hibernate.dialect.Dialect 的子类(我检查了源代码),在我看来,我在这里遇到了一些混合版本问题。转换发生在 org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.constructDialect() 方法中,但我不知道哪个 jar 部署了该类以更正它的版本。

【问题讨论】:

    标签: hibernate jboss7.x


    【解决方案1】:

    在你的配置中看起来都不错,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
    

    【讨论】:

    • 很好的提示,但对我没有帮助!还是谢谢!
    【解决方案2】:

    org.hibernate.dialect.Oracle12cDialect 不能转换为 org.hibernate.dialect.Dialect

    这是无稽之谈,因为 Oracle12cDialect 实现了方言。但是……

    问题

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

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

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

    modul1 和 modul2 有自己的自己的方言接口副本,因此它们不兼容。

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

           (modul 1)
    public Dialect foobarDialect;
    

    但是 modul 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.
    

    如何解决?

    您可以通过从与第一个模块相同的类加载器加载接口来解决坚果壳问题。

    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 加载一个休眠,任何其他模块都不会覆盖此基本负载。

    【讨论】:

    • 感谢您的出色解释,但它并没有解决我的问题!
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2015-01-12
      • 1970-01-01
      • 2016-09-16
      • 2021-11-23
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      • 2011-02-08
      相关资源
      最近更新 更多