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
相关产品推荐
相关产品推荐

