不能用Hibernate调用PostgreSQL的11个存储过程

Can#39;t call PostgreSQL#39;s 11 Stored Procedure with Hibernate(不能用Hibernate调用PostgreSQL的11个存储过程)

本文介绍了不能用Hibernate调用PostgreSQL的11个存储过程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

PostgreSQL 11 现在支持存储过程,我正在尝试使用 Hibernate 5.3.7.FinalPostgresql 42.2.5 JDBC 驱动程序 调用一个.在 PostgreSQL 11 之前,我们有可以使用 JPA 的 @NamedStoredProcedure 调用的函数.但是,函数是用 SELECT my_func(); 执行的,新的存储过程必须用 CALL my_procedure();

PostgreSQL 11 now supports stored procedures and I am trying to call one with Hibernate 5.3.7.Final and Postgresql 42.2.5 JDBC driver. Previous to PostgreSQL 11 we had functions that could be called with JPA's @NamedStoredProcedure. However, the functions were executed with SELECT my_func(); and the new stored procedures have to be executed with CALL my_procedure();

我正在尝试执行以下简单的存储过程:

I am trying to execute the following simple stored procedure:

CREATE OR REPLACE PROCEDURE p_raise_wage_employee_older_than(operating_years 
int, raise int)
AS $$
    BEGIN
       UPDATE employees
       SET wage = wage + raise 
       WHERE EXTRACT(year FROM age(entrance_date)) >= operating_years;
    END $$
LANGUAGE plpgsql;

JPA 注释如下所示:

The JPA annotation looks like the following:

@NamedStoredProcedureQuery(name = "raiseWage", 
   procedureName = "p_raise_wage_employee_older_than", 
   parameters = {
        @StoredProcedureParameter(name = "operating_years", type = Integer.class, 
           mode = ParameterMode.IN),
        @StoredProcedureParameter(name = "raise", type = Integer.class, 
            mode = ParameterMode.IN)
})

我正在调用存储过程:

StoredProcedureQuery storedProcedureQuery = this.em.createNamedStoredProcedureQuery("raiseWage"); 
storedProcedureQuery.setParameter("operating_years", 20);
storedProcedureQuery.setParameter("raise", 1000);
storedProcedureQuery.execute();

我的日志如下所示:

Hibernate: {call p_raise_wage_employee_older_than(?,?)}
2019-02-17 11:07:41.290  WARN 11168 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 42809
2019-02-17 11:07:41.291 ERROR 11168 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: p_raise_wage_employee_older_than(integer, integer) is a procedure
  Hinweis: To call a procedure, use CALL.
  Position: 15

第一个 Hibernate 日志表明 Hibernate 使用 call 来执行存储过程,但我得到一个 SQL 异常,即未使用 CALL.这是 Postgresql 11 之前的 Postgresql 方言中的错误吗?您可以将 FUNCTIONS 建模为 JPA 中的存储过程,因此使用了 SELECT 而不是 CALL?

The first Hibernate log is indicating that Hibernate uses call to execute the stored procedure but I am getting a SQL exception that CALL is not used. Is this a bug in the Postgresql dialect as previous to Postgresql 11 you were able to model the FUNCTIONS as stored procedures within JPA and therefore SELECT was used and not CALL?

推荐答案

由于 pgJDBC 42.2.5 是在 PostgreSQL 11 版本(2018 年 10 月)之前(2018 年 8 月)发布的,我认为这是目前内部的一个问题PostgreSQL 本身的 JDBC 驱动程序.我在 GitHub 存储库中创建了一个 问题.

As the pgJDBC 42.2.5 was released prior (Aug, 2018) to the PostgreSQL 11 release (Oct, 2018), I think this is currently a issue within the JDBC driver for PostgreSQL itself. I've created a issue within the GitHub repository.

对于解决方法,您可以将 STORED PROCEDURE 重写为 FUNCTION 并使用 @NamedStoredProcedureQuery 或直接与 JDBC 交互CallableStatement 例如:

For a workaround, you could rewrite the STORED PROCEDURE as a FUNCTION and use @NamedStoredProcedureQuery or directly interact with the JDBC CallableStatement e.g.:

Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/", "postgres", "postgres");

CallableStatement callableStatement = conn.prepareCall("{call f_raise_wage_employee_older_than(?,?)}");
callableStatement.setInt(1, 20);
callableStatement.setInt(2, 500);
callableStatement.executeUpdate();

或使用 EntityManager 执行本机查询:

Or execute a native query with the EntityManager:

this.em.createNativeQuery("CALL p_raise_wage_employee_older_than(1, 20)");

我会在收到 pgJDBC 维护者的答复后立即更新此答案.

I'll update this answer as soon as I get an answer from the pgJDBC maintainer.

更新:

Postgres 邮件列表(https://www.postgresql.org/message-id/4285.1537201440%40sss.pgh.pa.us)目前没有解决方案.唯一的方法是将本地 SQL 查询传递给数据库或将 STORED PROCEDURE 重写为 FUNCTION

This topic is already discussed in the Postgres Mailing list (https://www.postgresql.org/message-id/4285.1537201440%40sss.pgh.pa.us) and there is currently no solution. The only way is to pass native SQL queries to the database or rewrite the STORED PROCEDURE as a FUNCTION

这篇关于不能用Hibernate调用PostgreSQL的11个存储过程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:不能用Hibernate调用PostgreSQL的11个存储过程

基础教程推荐