传递枚举作为查询参数时触发十六进制字符异常求助
解决H2数据库中枚举参数传入原生SQL查询的报错问题
问题分析
报错Caused by: org.h2.jdbc.JdbcSQLDataException: Hexadecimal string contains non-hex character: "SWEDISH_MARKET"的核心原因有两个:
- 参数名不匹配:DAO方法中
@Param("licenseMarket")定义的参数名,与SQL语句里的:market不一致,导致参数未正确绑定,H2错误解析枚举类型。 - H2与PostgreSQL的枚举处理差异:PostgreSQL支持
cast :market as text将枚举转为字符串,但H2对原生SQL中的枚举参数默认解析逻辑不同,会将枚举实例错误识别为二进制/十六进制类型。
解决方案
步骤1:修正参数名匹配问题
先确保DAO方法的@Param参数名与SQL中的占位符完全一致,二选一修改即可:
- 方式A:修改SQL占位符
@Query(value = "SELECT count(*) " + "FROM Statements statements WHERE " + "market = :licenseMarket", nativeQuery = true) long countStatements(@Param("licenseMarket") Market market);
- 方式B:修改
@Param参数名
@Query(value = "SELECT count(*) " + "FROM Statements statements WHERE " + "market = :market", nativeQuery = true) long countStatements(@Param("market") Market market);
步骤2:兼容H2的枚举参数处理
修正参数名后,还需让H2正确识别枚举的字符串值,推荐两种通用方案:
方案一:直接传入枚举的字符串名称
修改方法参数为String,调用时传入枚举的name()值:
@Query(value = "SELECT count(*) FROM Statements statements WHERE market = :market", nativeQuery = true) long countStatements(@Param("market") String market); // 调用示例 countStatements(Market.SWEDISH_MARKET.name());
方案二:使用Spring Data SpEL表达式获取枚举名称
保持参数为枚举类型,通过SpEL表达式在原生SQL中直接提取枚举的字符串值,兼容PostgreSQL和H2:
@Query(value = "SELECT count(*) FROM Statements statements WHERE market = :#{#market.name()}", nativeQuery = true) long countStatements(@Param("market") Market market); // 调用方式不变 countStatements(Market.SWEDISH_MARKET);
注意事项
- 避免在H2中使用PostgreSQL的
cast :market as text语法,H2对枚举类型的CAST逻辑不兼容该写法。 - 若使用H2的内存数据库做测试,需确保实体类的
@Enumerated(EnumType.STRING)注解配置正确,与数据库字段类型(VARCHAR)匹配。
内容的提问来源于stack exchange,提问作者user9304291
相关产品推荐
相关产品推荐

