Spring Boot 2.3.12.RELEASE版本H2集成测试表不存在问题求助
问题原因
- 无效的初始化配置:你将
spring.datasource.data、spring.datasource.initialization-mode这两个Spring Boot上下文级别的配置写进了JDBC连接属性中,这类配置是Spring框架处理初始化逻辑用的,并不会被JDBC驱动识别,完全不生效。 - H2与MySQL方言不兼容:你的JPA配置指定了
org.hibernate.dialect.MySQL5InnoDBDialect方言,生成的建表语句会带engine=InnoDB等MySQL专属参数,但H2默认模式下不识别这类参数,会导致实际建表失败,你看到的Hibernate日志只是打印了要执行的SQL,没有打印执行异常。 - Spring Boot版本升级后自定义数据源初始化逻辑变更:Spring Boot 2.3+版本调整了数据源初始化规则,只有自动配置的数据源才会默认触发
schema.sql/data.sql执行、自动应用JPA建表配置,你自定义的writeDataSource没有绑定对应的初始化逻辑,导致建表操作实际没有在自定义数据源对应的H2实例中生效。 - H2版本行为变更:Spring Boot 2.3.12对应的H2版本比2.1.3的版本高,内存数据库默认隔离性更强,如果没有显式配置,不同连接可能拿到不同的内存库实例,即使加了
DB_CLOSE_DELAY=-1也可能出现建表和操作不在同一个库的问题。
解决方案
- 首先删除数据源配置中无效的连接属性,删掉以下两行代码:
props.setProperty("spring.datasource.data", "data.sql"); props.setProperty("spring.datasource.initialization-mode", "ALWAYS");
- 调整H2 JDBC URL,添加兼容配置,适配MySQL方言和内存库共享逻辑:
String dbUrl = "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MySQL;IGNORECASE=TRUE";
其中MODE=MySQL让H2兼容MySQL语法,IGNORECASE=TRUE关闭大小写敏感,避免驼峰表名和全大写报错不匹配的问题。
- 手动为自定义数据源添加初始化逻辑,如果你需要执行
data.sql导入初始数据,在配置类中添加DataSourceInitializer的Bean定义:
@Bean public DataSourceInitializer writeDataSourceInitializer(@Qualifier("writeDataSource") DataSource dataSource) { ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); // 导入schema和数据脚本,根据实际需求调整 populator.addScript(new ClassPathResource("data.sql")); populator.setContinueOnError(false); DataSourceInitializer initializer = new DataSourceInitializer(); initializer.setDataSource(dataSource); initializer.setDatabasePopulator(populator); initializer.setEnabled(true); return initializer; }
- 调整test环境的JPA配置,确保建表逻辑生效:在test环境的配置文件中添加以下配置,覆盖全局的ddl-auto配置:
spring: jpa: hibernate: ddl-auto: create-drop
测试执行完会自动销毁表,避免测试数据互相干扰。
- 检查多数据源配置,确保测试类上的事务管理器、Repository扫描都绑定了你配置的
writeTransactionManager和writeEntityManagerFactory,避免操作时拿到未初始化的其他数据源连接。
内容的提问来源于stack exchange,提问作者ViS
相关产品推荐
相关产品推荐

