【问题标题】:How to call a stored procedure(PostgreSQL) with Spring JPA?如何使用 Spring JPA 调用存储过程(PostgreSQL)?
【发布时间】:2021-09-02 21:10:00
【问题描述】:

PostgreSQL 程序:

CREATE OR REPLACE PROCEDURE public.create_task_by_device(task_id integer, device_ids text)
 LANGUAGE plpgsql
AS $procedure$
    begin
        -- do something here
    END;
$procedure$
;

Spring JPA:(Kotlin)

interface TaskTemplateRepository : JpaRepository<TaskTemplate, Int> {
    @Procedure("public.create_task_by_device")
    fun createTaskByDevice(@Param("task_id") taskId: Int, @Param("device_ids") device_ids: String)
}

例外:

org.postgresql.util.PSQLException: ERROR: public.create_task_by_device(integer, character varying) is a procedure. To call a procedure, use CALL.
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2553) ~[postgresql-42.2.20.jar:42.2.20]

然后我得到spring.jpa.show-sql: true执行的SQL语句{call public.create_task_by_device(?,?)}

看来实际执行的语句是call using call。

不明白为什么整句话都被{ ... }包围了

然后我尝试单步调试,org.postgresql.jdbc.PgStatement#execute方法中实际执行的SQL语句是select * from create_task_by_device(1,'2') as result,不像JPA在命令行输出的SQL语句,不知道为什么

最后,我尝试编写自己的 SQL 语句

    @Query("call public.create_task_by_device(?1, ?2)", nativeQuery = true)
    fun createTaskByDevice(@Param("task_id") taskId: Int, @Param("device_ids") device_ids: String)

我遇到了另一个异常org.postgresql.util.PSQLException: No results were returned by the query.

如果我在方法中添加@Modifying,则抛出javax.persistence.TransactionRequiredException: Executing an update/delete query

【问题讨论】:

    标签: spring postgresql spring-data-jpa spring-data


    【解决方案1】:

    尝试使用 : 作为占位符更改为 @Query -> (:task_id,:device_ids);

    @Query(value = "{call public.create_task_by_device(:task_id,:device_ids)}",nativeQuery = true)
    

    如果 SP 执行像 (Insert,Update) 这样的 DML 操作,请在 @Query 中添加以下注释;

    @Transactional 
    @Modifying(clearAutomatically = true)
    

    这是一个参考 -> https://www.baeldung.com/spring-data-jpa-stored-procedures#query-annotation

    【讨论】:

    • 它抛出org.postgresql.util.PSQLException: No results were returned by the query.
    • SP 执行 DQL 或 DML 什么样的操作?
    • 我更新了我的答案以指向您所指的异常。
    • 谢谢,它对我有用。提醒其他人,如果存储过程中有commit,则会抛出异常PSQLException: ERROR: invalid transaction termination。参考:postgresql.org/docs/14/sql-call.html
    猜你喜欢
    • 2021-03-15
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 1970-01-01
    • 2015-07-26
    • 2017-07-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多