You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring JPA @Query注解在H2数据库中执行失败求助

问题排查与修复方案

核心问题根源

你的代码中,Entity的列名使用了反引号包裹(如@Column(name = "disk_id")),但自定义原生SQL的UPDATE语句中未对列名做相同处理,加上H2内存数据库默认的标识符引用规则与预期不符,导致SQL语法解析失败。

修复步骤

1. 统一原生SQL的列名引用格式

修改@Query中的原生SQL,将列名用反引号包裹,与Entity配置保持一致:

@Transactional
@Modifying
@Query(value = "UPDATE m_target_disk SET `disk_state` = :tar_state WHERE "  +
    "`disk_state` = :ori_state AND `disk_id` = :disk_id", nativeQuery = true)
int updateDiskStateByDiskId(@Param("disk_id") String diskId, @Param("ori_state") String originState, @Param("tar_state") String targetState);

2. 调整H2数据库连接配置

在测试环境的H2数据库URL中添加模式参数,使其兼容MySQL的标识符引用规则(适配你用反引号的写法):

spring.datasource.url=jdbc:h2:mem:testdb;MODE=MySQL;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1
  • MODE=MySQL:让H2采用MySQL的SQL语法规则,支持反引号作为标识符包裹符
  • DATABASE_TO_UPPER=false:禁止H2自动将表名/列名转为大写,避免与你定义的小写列名不匹配

3. 验证枚举参数的一致性

确认DiskState枚举的字符串值与测试代码中传入的"AVAILABLE"、"USING"完全一致,比如枚举类定义:

public enum DiskState {
    AVAILABLE, USING
}

确保无大小写拼写错误,因为@Enumerated(EnumType.STRING)是严格匹配字符串值的。

4. 检查事务生效范围

在测试类上添加@Transactional注解,确保测试方法中的数据库操作在同一个事务内执行:

@Transactional
@Test
public void testSaveAndFind() {
    TargetDiskEntity result = repository.findByDiskId(diskEntity.getDiskId()).get();
    repository.updateDiskStateByDiskId(result.getDiskId(), "AVAILABLE", "USING");
}

验证方式

修改后重新运行单元测试,若Hibernate DEBUG日志中输出的SQL语句列名带反引号,且H2数据库能正确解析,即可解决语法异常问题。

内容的提问来源于stack exchange,提问作者DevCooper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 04:07:35