当将Spring Boot从2系版本升级时,如果H2出现错误,可以采取以下解决方法

概述

当我从Spring Boot 1.5系版本升级到Spring Boot 2系版本时,遇到了H2的错误,因此进行了调查。在这里,我将写下我在调查中所了解到的内容以及我是如何处理这个错误的。

每个库的版本在出现问题时。

ライブラリバージョンSpring Boot2.1.6H21.4.192

請問有什麼疑問嗎?

以下是错误的内容。
由于不支持isWrapperFor方法,它会抛出异常。

2020-01-16 00:09:52 JDBCX: exception
org.h2.jdbc.JdbcSQLException: 機能はサポートされていません: "isWrapperFor"
Feature not supported: "isWrapperFor" [50100-192]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
    at org.h2.message.DbException.get(DbException.java:179)
    at org.h2.message.DbException.get(DbException.java:155)
    at org.h2.message.DbException.getUnsupportedException(DbException.java:216)
    at org.h2.message.TraceObject.unsupported(TraceObject.java:375)
    at org.h2.jdbcx.JdbcDataSource.isWrapperFor(JdbcDataSource.java:422)
    at org.springframework.boot.jdbc.DataSourceUnwrapper.safeUnwrap(DataSourceUnwrapper.java:77)
    at org.springframework.boot.jdbc.DataSourceUnwrapper.unwrap(DataSourceUnwrapper.java:56)
    at org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration$HikariPoolDataSourceMetadataProviderConfiguration.lambda$hikariPoolDataSourceMetadataProvider$0(DataSourcePoolMetadataProvidersConfiguration.java:66)
    at org.springframework.boot.jdbc.metadata.CompositeDataSourcePoolMetadataProvider.getDataSourcePoolMetadata(CompositeDataSourcePoolMetadataProvider.java:50)
   ...

调查

从错误日志中看到,在Spring的DataSourceUnwrapper#safeUnwrap方法中发生了异常,所以我会去看一下。
https://github.com/spring-projects/spring-boot/blob/2.1.x/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceUnwrapper.java#L77

private static <S> S safeUnwrap(Wrapper wrapper, Class<S> target) {
    try {
        if (wrapper.isWrapperFor(target)) {
            return wrapper.unwrap(target);
        }
    }
    catch (Exception ex) {
        // Continue
    }
    return null;
}

有一個叫做isWrapper的方法被使用了。isWrapperFor是指這個方法。根據H2的情況來看,似乎不支援這個方法。
而且我查看了H2的changelog,找到了支持這一說法的記載。

PR #844:为JdbcDataSource添加isWrapperFor()和unwrap()的简单实现。

看起来,在1.4.197版本中,JdbcDataSource中添加了isWrapperFor方法的实现。似乎在Spring Boot 2.1.6中,实现是以isWrapperFor方法为前提的。但由于H2版本为1.4.192,所以没有这个方法会导致异常。

我会确认一下Spring Boot 2.1.6具体依赖的是H2的哪个版本。

查看Maven Repository后,首先发现Spring Boot(Spring Boot JDBC Starter)2.1.6依赖于Spring JDBC 5.1.8,而Spring JDBC 5.1.8又依赖于H2 1.4.199。因此,可以得出结论,Spring Boot 2.1.6依赖于H2 1.4.199,这样就能对上了。

顺便说一下,在Spring Boot 1.5系列中没有出现错误的原因是因为没有DataSourceUnwrapper#safeUnwrap方法,所以isWrapperFor方法没有被调用。

解决方案 (Jiě jué cè àn)

将H2的版本升级至1.4.199。

    ...
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <version>1.4.199</version>
    </dependency>
    ...

这样就不会再报错了。

总结了

在这次升级到Spring Boot 2.x版本时,我们进行了对H2错误的原因调查和解决。
最终各个库的版本如下。

ライブラリバージョンSpring Boot2.1.6H21.4.199

作为教训,当更新框架或库时,应该通过更改日志或发布说明来确认依赖库的版本以及与上个版本的变化。这样可以在一定程度上检查变化如何影响行为。
如果使用maven等进行库管理,可以通过查看MavenRepository来检查依赖库的版本。在MavenRepository中,可以直接跟随链接进行查询。
我认为,由于更改日志和发布说明通常都在官方网站或Github上发布,所以查看它们可能会很有帮助。

广告
将在 10 秒后关闭
bannerAds