使用JPA Repository调用Oracle函数遇ORA-06550参数错误
问题分析
你遇到的PLS-00306错误,核心原因是用JPA的@Procedure注解调用Oracle函数的方式错误:
- 你的
Storicizza是带返回值的Oracle函数,它通过RETURN语句返回结果,本身没有输出参数; - 但
@Procedure注解是为调用存储过程设计的,JPA会自动把你指定的outputParameterName当成一个额外的输出参数传递给函数,导致生成的SQL多了一个参数(NIDACCREDTARGET=>:5),和函数定义的5个输入参数不匹配,触发参数数量错误。
从生成的SQL能明确问题:
BEGIN PCK_STO.Storicizza(PIDACCRED=>:0,PUSER=>:1,PCOGNOMENOME=>:2,PCODICEFISCALE=>:3,PVERSIONE=>:4,NIDACCREDTARGET=>:5); END;
函数定义仅需5个输入参数,这里却传递了6个,自然触发参数不匹配报错。
解决方案
Oracle函数的正确调用方式是通过SELECT语句执行,而非存储过程的CALL语法,推荐以下两种实现方式:
方法1:使用@NamedNativeQuery
在对应的实体类(比如Acc0000Accreditamenti)上定义原生查询:
@Entity @NamedNativeQuery( name = "Acc0000Accreditamenti.storicizza", query = "SELECT PCK_STO.Storicizza(:pIdAccred, :pUser, :pCognomeNome, :pCodiceFiscale, :pVersione) FROM DUAL", resultClass = Long.class ) public class Acc0000Accreditamenti { // 实体类字段定义... }
然后在Repository中定义对应方法:
public interface Acc0000AccreditamentiRepository extends JpaRepository<Acc0000Accreditamenti, Long> { @Query(name = "Acc0000Accreditamenti.storicizza", nativeQuery = true) Long storicizza(@Param("pIdAccred") Long idAccreditamento, @Param("pUser") String user, @Param("pCognomeNome") String nomeCognome, @Param("pCodiceFiscale") String codFiscale, @Param("pVersione") Long versione); }
方法2:直接用@Query写原生SQL
如果不想在实体类上加注解,也可以直接在Repository方法上编写原生查询:
public interface Acc0000AccreditamentiRepository extends JpaRepository<Acc0000Accreditamenti, Long> { @Query(value = "SELECT PCK_STO.Storicizza(:pIdAccred, :pUser, :pCognomeNome, :pCodiceFiscale, :pVersione) FROM DUAL", nativeQuery = true) Long storicizza(@Param("pIdAccred") Long idAccreditamento, @Param("pUser") String user, @Param("pCognomeNome") String nomeCognome, @Param("pCodiceFiscale") String codFiscale, @Param("pVersione") Long versione); }
额外检查点
- 确保JPA传递的参数类型和Oracle函数的参数类型完全匹配:比如
acc0000_accreditamenti.id%TYPE如果是NUMBER(10),用Long没问题;字符串类型要对应Oracle的VARCHAR2; - 确认数据库用户拥有调用
PCK_STO.Storicizza函数的权限。
内容的提问来源于stack exchange,提问作者Andrea
相关产品推荐
相关产品推荐

