Wildfly 11 - 更新到 Hibernate 5。2.x for "Native Hibernate use"

Wildfly 11 - update to Hibernate 5.2.x for "Native Hibernate use"

背景:WAR 应用程序在 "Native Hibernate use" 场景中利用 Spring + Hibernate (https://docs.jboss.org/author/display/WFLY/JPA+Reference+Guide#JPAReferenceGuide-NativeHibernateuse)

使用与 WFLY 11 捆绑的 Hibernate 版本(即 5.1.10.Final)时,一切都按预期工作,在 jboss-deployment-structure.xml 中针对 org.hibernate 模块进行以下配置:

<jboss-deployment-structure>
    <deployment>
        <dependencies>
            ...
            <module name="org.hibernate"/>
            ...
        </dependencies>
        <exclude-subsystems>
            <subsystem name="jaxrs" />
        </exclude-subsystems>
    </deployment>
</jboss-deployment-structure>

升级到 Hibernate 5.2 时出现问题。16.Final 根据 this guide。据我了解,在模块目录中解压 hibernate-orm-modules-5.2.16.Final-wildfly-11-dist.zip 后,我应该能够定义带有插槽 5.2 或 5.2 的 Hibernate 模块。16.Final,即:

<jboss-deployment-structure>
    <deployment>
        <dependencies>
            ...
            <module name="org.hibernate" slot="5.2"/>
            ...
        </dependencies>
        <exclude-subsystems>
            <subsystem name="jaxrs" />
        </exclude-subsystems>
    </deployment>
</jboss-deployment-structure>

但是上面的配置结果是

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.hibernate.SessionFactory' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1507)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:815)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:721)
    ... 32 more

同时将 <module name="org.hibernate" slot="5.2"/> 更改为例如<module name="org.hibernate" slot="5.23456789"/> Wildfly 抛出这样的模块版本不存在的异常,所以我假设模块已正确加载。

我在这个配置中遗漏了什么吗?添加 persistence.xml<property name="jboss.as.jpa.providerModule" value="org.hibernate:5.2"/> 不适用于这种情况,因为我不使用由 Wildfly 管理并注入 @PersistenceContext 注释的持久性单元。

我终于找到了解决问题的方法。

我尝试将 "Native Hibernate use" 模式转换为 Wildfly-managed 实体管理器(这意味着引入 persistence.xml 和 Spring LocalContainerEntityManagerFactoryBean 负责解析 persistence.xml)。这引入了另一种异常,它们是 app- 或 configuration-specific,在这种情况下无关紧要。

真正有用的是记录由 WFLY 类加载器 ($JAVA_OPTS += '-verbose:class') 加载的 jar。事实证明,无论指定插槽(<module name="org.hibernate" slot="5.2"/> - 或者在 persistence.xml 的情况下:<property name="jboss.as.jpa.providerModule" value="org.hibernate:5.2"/>),WFLY 总是从 main 加载一些核心 类(例如 SessionFactory)在最好的情况下导致链接异常或在最坏的情况下导致 'silent' 错误的插槽。

有用的是用与 ${jboss.home.dir}/modules/system/layers/base/org/hibernate/5.2/module.xml 相同的内容替换主休眠 module.xml (${jboss.home.dir}/modules/system/layers/base/org/hibernate/main/module.xml),这意味着现在我的 ${jboss.home.dir}/modules/system/layers/base/org/hibernate/main/module.xml 看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>

<module-alias xmlns="urn:jboss:module:1.3"
    name="org.hibernate" slot="main"
    target-name="org.hibernate" target-slot="5.2.16.Final"
/>

无论 'main' 或 '5.2' 插槽如何,Wildfly 都会加载正确版本的 Hibernate jar,因为它们都指向相同的 Hibernate 版本。

该解决方案适用于 persistence.xml 模式以及 "Native Hibernate use" 模式。