H2自定义函数可在WHERE子句使用但SELECT子句访问失败问题排查
问题产生原因
- 默认
@Query注解的内容是JPQL语句而非原生SQL,JPQL解析校验阶段只会识别标准语法和内置函数,你自定义的H2函数ANOTHERTEST返回自定义User实体类型,JPQL无法识别该返回类型的实体映射规则,直接触发查询校验失败异常。 repoFunction1能正常运行的原因是TEST函数返回Integer基础类型,JPQL支持基础类型的等值比较逻辑,不会触发校验失败。- 即便你改用原生SQL,直接给自定义函数传
u(整条实体记录)的写法也不符合SQL语法规则,SQL层面只能传递表的具体字段值,无法直接将整条行记录作为Java实体参数传入自定义函数。 - 你尝试将schema.sql重命名为import.sql没有效果,是因为该问题和SQL脚本的初始化执行时机无关,属于查询写法和自定义函数的使用错误。
解决方法
1. 调整自定义函数入参
修改CustomH2类的customAnotherTestFunction方法,改为接收具体字段值,手动构造User对象返回:
package com.example.demospringbootproject.h2; import com.example.demospringbootproject.model.User; public class CustomH2 { public static Integer customTestFunction(Integer id){ return id; } // 调整此处入参为具体的id、name字段 public static User customAnotherTestFunction(Integer id, String name){ User user = new User(); user.setId(id); user.setName(name); return user; } }
2. 调整Repository查询写法
修改repoFunction2的@Query注解,开启原生查询,传递具体字段值到自定义函数:
// 开启nativeQuery = true 走原生SQL逻辑,表名用schema中定义的小写user @Query(value = "Select ANOTHERTEST(u.id, u.name) From user u where u.id = 1", nativeQuery = true) User repoFunction2();
如果调整后仍出现结果映射问题,可以给返回结果添加SqlResultSetMapping注解配置自定义实体的映射规则,简单场景下以上两步修改即可正常运行。
内容的提问来源于stack exchange,提问作者Usama Abubakar
相关产品推荐
相关产品推荐

