[spring-projects/spring-boot]容忍休眠 5.2

2018-11-05 488 views
9

在尝试升级我们的应用程序以使用 Spring Boot 2.1.0 时,我在 Hibernate 初始化时遇到了一个问题。我们目前使用 Hibernate 5.2.x,据我所知 Spring Boot 2.1.0 应该仍然支持这个版本。但是,在 Spring Boot JPA 自动配置期间似乎对 Hibernate 5.3.x 存在显式依赖。在 Hibernate 5.2.x 中,当HibernateJpaConfiguration类执行引导 Hibernate 时,ClassNotFoundException会抛出 a 错误,因为它无法找到 Hibernate 5.3.x 的新类 BeanContainer。

Caused by: java.lang.ClassNotFoundException: org.hibernate.resource.beans.container.spi.BeanContainer
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    ... 45 common frames omitted

问题看起来出在HibernateJpaConfiguration.determineHibernatePropertiesCustomizers实例化SpringBeanContainer.

我附上了一个从 Spring Initializr 生成的超级简单项目来演示该问题。我在创建项目后所做的唯一更改是将属性设置hibernate.version5.2.17.Final.只需运行 Maven 构建或启动应用程序即可查看问题。

查看源代码后,在初始化期间似乎没有条件检查来确定该类是否BeanContainer可用。我认为我们需要类似的东西LocalSessionFactoryBean

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        if (beanFactory instanceof ConfigurableListableBeanFactory &&
                ClassUtils.isPresent("org.hibernate.resource.beans.container.spi.BeanContainer",
                        getClass().getClassLoader())) {
            this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
        }
    }

spring-boot-hibernate-problem-demo.zip

回答

1

我们可以考虑将此设置为条件,但请注意,我们通常会尝试避免编写代码来支持同一依赖项的多个次要版本,特别是早于我们编译的版本的次要版本。

据我所知 Spring Boot 2.1.0 应该仍然支持这个版本

您能指出这一印象的来源吗?我想确保我们的文档没有误导性。

8

@garethpowell 有什么特定的因素阻止您升级到 Hibernate 5.3 吗?

4

这不仅仅是BeanContainer。我们还使用RegionFactoryTemplate5.3 中的另一个附加功能。

5

实际上,这不是我们,而是另一个 Hibernate 模块。这表明当 5.3 位于类路径上时,测试我们是否与 5.2 兼容是很困难的。

7

@wilkinsona我想我推断Spring Boot将/应该基于Spring 5.x的支持继续支持旧版本的Hibernate。我认为 Spring Boot 不应该强制用户进行特定的升级,因为 5.2 和 5.3 之间存在重大变化,特别是缓存 SPI,因此我们目前不能简单地升级到 5.3 @philwebb。我们在 AWS 中使用 Elasticache 作为后端,支持此功能的库尚不适用于 Hibernate 5.3。我一直在寻找替代方案,但到目前为止还没有找到合适的。

从 Spring Framework 5.0 开始,Spring 需要 Hibernate ORM 4.3 或更高版本来支持 JPA,甚至需要 Hibernate ORM 5.0+ 来针对本机 Hibernate Session API 进行编程。请注意,Hibernate 团队不再维护 5.1 之前的任何版本,并且可能很快会专门关注 5.3+。

4

Spring Boot 对事物的看法比 Spring Framework 更加固执己见,因此您不能安全地假设,因为 Framework 支持特定范围的依赖项版本,所以 Boot 也会做同样的事情。

一般来说,第三方项目更注重向后兼容性而不是向前兼容性。这意味着覆盖 Boot 的依赖管理以升级到新的次要版本通常是安全的,但降级到较旧的次要版本的覆盖可能不起作用。

在我看来,这更像是 Elasticache Hibernate 集成的问题。您是否考虑过坚持使用 Boot 2.0.x,直到实现 Hibernate 5.3 兼容性?

2

作为一个组织,我们努力在新版本可用时与 Spring 和其他核心库保持同步,从而避免任何大的改变。我很欣赏 Spring Boot 的固执己见的方法,这在大多数情况下都非常有效。我可以理解对 5.x 之前的 Hibernate 兼容性的支持被删除,但我忍不住认为这将阻止大量用户升级到 Spring Boot 2.1(如果他们也被迫更新到 Hibernate 5.3)。不管怎样,我们至少会在 Boot 2.0 上停留一段时间。感谢您对这个问题的及时回复。

2

据我所知,使用我们的 ModifiedClassPathRunner 测试对 5.2 的支持是不可能的。 Hibernate 坚持使用系统类加载器,即使它不是加载 Hibernate 的类加载器的祖先。这可以防止我们隐藏 Hibernate 5.3 类。

5

对主代码的更改相对简单,但测试却并非如此。我们不想在没有经过 Boot 测试验证的情况下进行旨在支持 Hibernate 5.2 的更改。

8

啊,对了。我现在和你在一起。我已经开始寻找替代方案来删除阻止我们升级到 Hibernate 5.3 的缓存库依赖项。

2

FWIW,Hibernate 团队不再支持 Hibernate ORM 5.2 系列。他们似乎认为 5.3 会立即取代 5.2 系列。实际上,他们此时只维护 5.3.x 和 5.1.x 行...这是有道理的,因为 5.2 是合并了 Hibernate/JPA API 的重大修订,因此大多数人宁愿停留在 5.1.x 上二进制兼容性原因(或者因为它是随 JBoss EAP 安装一起提供的)...或者能够相当快地转移到 5.3。

9

太棒了@wilkinsona。非常感谢。