升级Spring Boot至2.7.5后H2数据库CONSTANTS表不存在异常求助
问题描述
将spring-boot-starter-parent从2.6.8升级到2.7.5后,单元测试中出现H2数据库异常,提示不存在业务中未定义的CONSTANTS表。
异常栈跟踪
org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "CONSTANTS" not found
org.dbunit.dataset.DataSetException: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "CONSTANTS" not found; SQL statement: select CONSTANT_CATALOG, CONSTANT_SCHEMA, CONSTANT_NAME, VALUE_DEFINITION, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, CHARACTER_SET_NAME, COLLATION_CATALOG, COLLATION_SCHEMA, COLLATION_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, DATETIME_PRECISION, INTERVAL_TYPE, INTERVAL_PRECISION, MAXIMUM_CARDINALITY, DTD_IDENTIFIER, DECLARED_DATA_TYPE, DECLARED_NUMERIC_PRECISION, DECLARED_NUMERIC_SCALE, GEOMETRY_TYPE, GEOMETRY_SRID, REMARKS from CONSTANTS [42102-214] at org.dbunit.database.DatabaseDataSet.getTable(DatabaseDataSet.java:342) at org.dbunit.database.DatabaseTableIterator.getTable(DatabaseTableIterator.java:89) at org.dbunit.dataset.stream.DataSetProducerAdapter.produce(DataSetProducerAdapter.java:83) at org.dbunit.dataset.xml.FlatXmlWriter.write(FlatXmlWriter.java:124) at org.dbunit.dataset.xml.FlatXmlDataSet.write(FlatXmlDataSet.java:378) at my.own.package.util.Test.extractDataSet(AbstractJobIntegrationTest.java:221) at my.own.package.configuration.util.AbstractJobIntegrationTest.getActualMidasConfigurationDataSet(AbstractJobIntegrationTest.java:206) at my.own.package.configuration.util.Test.assertDatabase(AbstractJobIntegrationTest.java:197) at my.own.package.configuration.IntegrationTest.testSuccess(CallCreditIntegrationTest.java:76) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725) at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84) at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115) at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86) at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86) at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54) Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "CONSTANTS" not found; SQL statement: select CONSTANT_CATALOG, CONSTANT_SCHEMA, CONSTANT_NAME, VALUE_DEFINITION, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, CHARACTER_SET_NAME, COLLATION_CATALOG, COLLATION_SCHEMA, COLLATION_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, DATETIME_PRECISION, INTERVAL_TYPE, INTERVAL_PRECISION, MAXIMUM_CARDINALITY, DTD_IDENTIFIER, DECLARED_DATA_TYPE, DECLARED_NUMERIC_PRECISION, DECLARED_NUMERIC_SCALE, GEOMETRY_TYPE, GEOMETRY_SRID, REMARKS from CONSTANTS [42102-214] at org.h2.message.DbException.getJdbcSQLException(DbException.java:502) at org.h2.message.DbException.getJdbcSQLException(DbException.java:477) at org.h2.message.DbException.get(DbException.java:223) at org.h2.message.DbException.get(DbException.java:199) at org.h2.command.Parser.getTableOrViewNotFoundDbException(Parser.java:8398) at org.h2.command.Parser.getTableOrViewNotFoundDbException(Parser.java:8369) at org.h2.command.Parser.readTableOrView(Parser.java:8358) at org.h2.command.Parser.readTablePrimary(Parser.java:1863) at org.h2.command.Parser.readTableReference(Parser.java:2334) at org.h2.command.Parser.parseSelectFromPart(Parser.java:2772) at org.h2.command.Parser.parseSelect(Parser.java:2878) at org.h2.command.Parser.parseQueryPrimary(Parser.java:2762) at org.h2.command.Parser.parseQueryTerm(Parser.java:2633) at org.h2.command.Parser.parseQueryExpressionBody(Parser.java:2612) at org.h2.command.Parser.parseQueryExpressionBodyAndEndOfQuery(Parser.java:2605) at org.h2.command.Parser.parseQueryExpression(Parser.java:2598) at org.h2.command.Parser.parseQuery(Parser.java:2567) at org.h2.command.Parser.parsePrepared(Parser.java:724) at org.h2.command.Parser.parse(Parser.java:689) at org.h2.command.Parser.parse(Parser.java:661) at org.h2.command.Parser.prepareCommand(Parser.java:569) at org.h2.engine.SessionLocal.prepareLocal(SessionLocal.java:631) at org.h2.engine.SessionLocal.prepareCommand(SessionLocal.java:554) at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1116) at org.h2.jdbc.JdbcStatement.executeQuery(JdbcStatement.java:92) at com.zaxxer.hikari.pool.ProxyStatement.executeQuery(ProxyStatement.java:110) at com.zaxxer.hikari.pool.HikariProxyStatement.executeQuery(HikariProxyStatement.java) at org.dbunit.database.AbstractResultSetTable.<init>(AbstractResultSetTable.java:110) at org.dbunit.database.ForwardOnlyResultSetTable.<init>(ForwardOnlyResultSetTable.java:59) at org.dbunit.database.CachedResultSetTableFactory.createTable(CachedResultSetTableFactory.java:60) at org.dbunit.database.DatabaseDataSet.getTable(DatabaseDataSet.java:338) ... 77 more
相关配置
application.yml
app: datasource: mydb-configuration: jdbcUrl: jdbc:h2:mem:db;DB_CLOSE_DELAY=-1;NON_KEYWORDS=VALUE username: sa password: driver-class-name: org.h2.Driver
pom.xml
... <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.5</version> <relativePath /> </parent> ... <dependency> <groupId>org.dbunit</groupId> <artifactId>dbunit</artifactId> <version>2.7.3</version> </dependency> ...
解决方案
这个问题的根源是Spring Boot 2.7.x升级了H2数据库版本,而DBUnit 2.7.3在处理H2的元数据查询时,会尝试访问H2新版本中不再存在的CONSTANTS系统表。
可以通过以下几种方式解决:
1. 升级DBUnit到兼容版本
将DBUnit版本升级到2.7.4或更高,新版本已经修复了对H2新版本的元数据查询兼容问题。修改pom.xml中的DBUnit依赖:
<dependency> <groupId>org.dbunit</groupId> <artifactId>dbunit</artifactId> <version>2.7.4</version> </dependency>
2. 配置DBUnit过滤系统表
如果暂时无法升级DBUnit,可以在DBUnit获取数据集时,过滤掉系统表(包括CONSTANTS)。修改extractDataSet方法,指定只包含业务相关的表,或者排除系统表:
// 示例:只提取指定业务表 QueryDataSet queryDataSet = new QueryDataSet(connection); queryDataSet.addTable("your_table_1"); queryDataSet.addTable("your_table_2"); FlatXmlDataSet.write(queryDataSet, new FileOutputStream("actual.xml"));
或者使用DatabaseConfig配置过滤:
DatabaseConfig config = databaseConnection.getConfig(); config.setProperty(DatabaseConfig.PROPERTY_TABLE_TYPE, new String[]{"TABLE"}); // 只加载用户表,排除系统表
3. 修改H2连接参数
在H2的JDBC URL中添加MODE=LEGACY参数,让H2以兼容模式运行,保留旧版本的系统表结构:
jdbcUrl: jdbc:h2:mem:db;DB_CLOSE_DELAY=-1;NON_KEYWORDS=VALUE;MODE=LEGACY
内容的提问来源于stack exchange,提问作者kamal
相关产品推荐
相关产品推荐

