PostgreSQL自定义函数SpringBoot调用报错:无匹配函数及参数类型
问题详情
在PostgreSQL数据库中定义了schema1.ven_totais_nfes函数,参数类型为date、date、text[],直接执行SQL脚本可正常返回结果;但在SpringBoot后端通过EntityManager调用该函数时,出现错误:ERROR: function ven_totais_nfes(unknown, unknown, uuid) does not exist,提示无匹配函数及参数类型,需显式类型转换。
PostgreSQL函数定义
CREATE OR REPLACE FUNCTION schema1.ven_totais_nfes(data_inicial date, data_final date, setor_usuario text[]) RETURNS TABLE(status character varying, quantidade bigint, valor numeric) LANGUAGE plpgsql SET search_path TO 'schema1', '$user', 'public' AS $function$ declare item record; begin [...] $function$;
手动执行的SQL脚本
select * from ven_totais_nfes('2022-12-01', '2022-12-31', array['aef4786e-7d99-4fdc-a20a-4da11c168eb2'])
SpringBoot调用代码
public List<NFeTotaisViewDto> findTotais(Date dataInicial, Date dataFinal, List<UUID> setorUsuario) { Query query = entityManager.createNativeQuery("select * from ven_totais_nfes(:dataInicial, :dataFinal, :setorUsuario)"); query.setParameter("dataInicial", dataInicial); query.setParameter("dataFinal", dataFinal); query.setParameter("setorUsuario", setorUsuario); // 省略后续映射及返回逻辑 }
错误原因
- 参数类型不匹配:函数第三个参数为
text[],但SpringBoot传入的List<UUID>会被JDBC驱动映射为PostgreSQL的uuid类型,最终参数类型变为uuid[],与函数定义的text[]不匹配。 - 日期参数隐式识别问题:手动执行时日期字符串会被PostgreSQL自动转换为
date类型,但通过EntityManager传入Date对象时,可能被识别为unknown类型,未正确映射到date。
解决方法
方法1:SQL中显式转换参数类型
修改NativeQuery的SQL语句,对参数进行强制类型转换:
public List<NFeTotaisViewDto> findTotais(Date dataInicial, Date dataFinal, List<UUID> setorUsuario) { String sql = "select * from ven_totais_nfes(" + ":dataInicial::date, " + ":dataFinal::date, " + ":setorUsuario::text[])"; Query query = entityManager.createNativeQuery(sql); query.setParameter("dataInicial", dataInicial); query.setParameter("dataFinal", dataFinal); query.setParameter("setorUsuario", setorUsuario); // 后续逻辑 }
方法2:将UUID列表转换为字符串列表传入
在Java代码中把List<UUID>转为List<String>,确保传入的是字符串数组,匹配函数的text[]参数,同时显式指定日期参数类型:
public List<NFeTotaisViewDto> findTotais(Date dataInicial, Date dataFinal, List<UUID> setorUsuario) { List<String> setorUsuarioStr = setorUsuario.stream() .map(UUID::toString) .collect(Collectors.toList()); Query query = entityManager.createNativeQuery("select * from ven_totais_nfes(:dataInicial, :dataFinal, :setorUsuario)"); query.setParameter("dataInicial", dataInicial, TemporalType.DATE); query.setParameter("dataFinal", dataFinal, TemporalType.DATE); query.setParameter("setorUsuario", setorUsuarioStr); // 后续逻辑 }
方法3:修改PostgreSQL函数参数类型(可选)
如果业务允许,将函数第三个参数改为uuid[],直接匹配传入的UUID列表:
CREATE OR REPLACE FUNCTION schema1.ven_totais_nfes(data_inicial date, data_final date, setor_usuario uuid[]) RETURNS TABLE(status character varying, quantidade bigint, valor numeric) LANGUAGE plpgsql SET search_path TO 'schema1', '$user', 'public' AS $function$ declare item record; begin [...] $function$;
注意:修改后手动执行SQL时,需传入uuid[]类型,例如:array['aef4786e-7d99-4fdc-a20a-4da11c168eb2']::uuid[]
内容的提问来源于stack exchange,提问作者Altair Todescatto F
相关产品推荐
相关产品推荐

