Spring Boot仓库测试中H2缺失PostgreSQL函数引发InvalidDataAccessResourceUsageException
解决方案
方案1:在H2中自定义DATE_PART函数
H2支持通过SQL自定义函数模拟PostgreSQL专属函数,可在测试初始化阶段执行脚本创建:
- 创建初始化脚本(比如
src/test/resources/init-h2-functions.sql):
CREATE ALIAS DATE_PART FOR "com.yourpackage.H2FunctionUtils.datePart";
- 编写Java工具类实现函数逻辑(匹配PostgreSQL周计算规则,默认周一起始、周数从1开始):
package com.yourpackage; import java.sql.Date; import java.time.LocalDate; import java.time.temporal.WeekFields; import java.util.Locale; public class H2FunctionUtils { public static long datePart(String part, Date date) { if ("week".equalsIgnoreCase(part)) { LocalDate localDate = date.toLocalDate(); WeekFields weekFields = WeekFields.of(Locale.ENGLISH); return localDate.get(weekFields.weekOfWeekBasedYear()); } // 可扩展支持year、month等其他DATE_PART参数 throw new UnsupportedOperationException("Unsupported part: " + part); } }
- 在测试类中加载脚本:
@DataJpaTest @Sql(scripts = "/init-h2-functions.sql") public class FraudReviewEventRepositoryTest { // 原有测试逻辑保持不变 }
方案2:升级H2版本至原生兼容DATE_PART的版本
H2 2.1.210及以上版本在PostgreSQL兼容模式下已原生支持DATE_PART函数,直接升级依赖即可:
Maven依赖示例:
<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>2.2.224</version> <scope>test</scope> </dependency>
Gradle依赖示例:
testImplementation 'com.h2database:h2:2.2.224'
升级后保持原JDBC URL配置(MODE=PostgreSQL),无需修改查询代码。
方案3:用H2的EXTRACT函数分环境替换查询
如果仅需支持week参数,可通过Spring Profile区分生产与测试环境的查询:
- 生产环境Repository(保留PostgreSQL原生查询):
@Repository @Profile("!test") public interface MyEntityRepositoryProd extends JpaRepository<MyEntity, Long>, JpaSpecificationExecutor<MyEntity> { @Query(value = "SELECT * FROM my_entity t " + "WHERE t.column = :val1 " + "AND DATE_PART('week', t.date_column) = :val2", nativeQuery = true) List<MyEntity> fooBar(Long val1, Long val2); }
- 测试环境Repository(使用H2兼容的EXTRACT函数):
@Repository @Profile("test") public interface MyEntityRepositoryTest extends JpaRepository<MyEntity, Long>, JpaSpecificationExecutor<MyEntity> { @Query(value = "SELECT * FROM my_entity t " + "WHERE t.column = :val1 " + "AND EXTRACT(WEEK FROM t.date_column) = :val2", nativeQuery = true) List<MyEntity> fooBar(Long val1, Long val2); }
需确保测试环境激活test Profile,比如在application-test.properties中添加spring.profiles.active=test。
内容的提问来源于stack exchange,提问作者gsan
相关产品推荐
相关产品推荐

