H2数据库不支持Sysdate导致功能测试用例无法运行的问题咨询
问题核心
JPQL中直接使用了Oracle专有函数SYSDATE,不属于JPA标准定义的通用函数,因此不支持跨数据库兼容。
适配方案
方案1:使用JPA标准日期函数(优先推荐)
JPA 2.1及以上版本提供的标准日期函数CURRENT_DATE(仅日期精度)、CURRENT_TIMESTAMP(日期+时间精度),所有兼容JPA规范的数据库驱动会自动映射为数据库本地对应的当前时间函数:Oracle侧自动转为SYSDATE,H2侧自动匹配原生当前时间函数,无需拆分多套查询语句,也无需额外配置。
修改后的查询代码如下:
@Query("SELECT new com......Test( " + "p.id,p.keyId, p.keyType, p.expiryDate...., CURRENT_DATE) " + "FROM TableA p " + "WHERE CURRENT_DATE < p.expiryDate ......") List<EnableEncryptionKeyProjection> findBySrcClientId(....);
方案2:H2侧配置SYSDATE别名(零业务代码侵入)
如果不想修改已有的JPQL业务代码,可以仅在测试环境的H2数据库配置中增加别名映射,让H2识别SYSDATE函数。
Spring Boot测试配置示例:
spring: datasource: url: jdbc:h2:mem:testdb;INIT=CREATE ALIAS IF NOT EXISTS SYSDATE FOR "java.time.LocalDateTime.now" driver-class-name: org.h2.Driver
也可以在H2初始化执行的SQL脚本中添加别名定义:
CREATE ALIAS IF NOT EXISTS SYSDATE FOR "java.time.LocalDateTime.now";
方案3:动态传入当前时间参数(最高灵活度)
如果需要支持测试场景下自定义时间做过期边界校验,可以把当前时间作为参数传入查询语句,完全不依赖数据库的时间函数实现,适配所有数据库类型。
代码示例:
@Query("SELECT new com......Test( " + "p.id,p.keyId, p.keyType, p.expiryDate...., :now) " + "FROM TableA p " + "WHERE :now < p.expiryDate ......") List<EnableEncryptionKeyProjection> findBySrcClientId(@Param("now") LocalDateTime now, ....);
业务调用时传入LocalDateTime.now()即可,测试场景可直接传入指定时间值做用例验证。
内容的提问来源于stack exchange,提问作者Jeff Cook
相关产品推荐
相关产品推荐

