質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

2回答

5127閲覧

spring bootからpostgresql12のprocedureを呼びたい

lahaina

総合スコア8

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

0クリップ

投稿2021/07/23 02:58

前提・実現したいこと

spring boot内で、SimpleJdbcCallを介して、postgresql(version12)のstored procedureを呼びたいのですが、エラーが出てしまいます。
作業環境は以下の通りです。
windows 10
spring boot 2.5.0
postgresql 12
jdbc

発生している問題・エラーメッセージ

Exception in thread "main" org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{call demo()}]; nested exception is org.postgresql.util.PSQLException: ERROR: demo() is a procedure
ヒント: To call a procedure, use CALL.
位置: 15
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:101)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:70)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:79)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:79)
at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1541)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1206)
at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1245)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:412)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:372)
at org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:198)

該当のソースコード

spring boot内でprocedureを呼んでいる部分は以下の通りです。
以下のexecuteを実行する際に上記エラーが出ます。

java

1SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate.getDataSource()) 2 .withProcedureName("demo") 3MapSqlParameterSource in = new MapSqlParameterSource() 4Map<String, Object> out = call.execute(in);//ここでエラー。

postgresqlのstored procedureは以下の通りです。テスト用のため中身は空にしています。

sql

1CREATE OR REPLACE PROCEDURE public.demo() 2 LANGUAGE plpgsql 3AS $procedure$ 4begin 5end 6$procedure$

試したこと

slf4jを用いてspring bootから発行されたsql文を確認すると以下のように表示されます。
INFO 10908 --- [ main] jdbc.sqlonly : {call demo()}
ERROR 10908 --- [ main] jdbc.sqlonly : 1. CallableStatement.execute() {call demo()}
これを見る限りではcallを使用してprcedureを呼んでいるようですが、上記エラーメッセージではprocedureを呼ぶためにはcallを使用するように指摘されています。

なお、SimpleJdbcCallに替えて、直接sql文を書くように変更した場合、エラーなくprocedureを呼べます(以下)。

java

1int price = jdbcTemplate.queryForObject("call get_price(?)", Integer.class,1000);

不足している情報があればご指摘下さい。補足させていただきます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

回答ありがとうございます。その後自分で調べられた限りですが、本件につき以下にいくつか補足します。

postgresqlのstored procedureはversion11から導入され、まだ期間が短いためにサポートが十分でない部分があるようです。jdbcを介してprocedureを呼ぶと同様の現象が出ていたことが公式のmailing listで議論されています(以下)。
https://www.postgresql.org/message-id/4285.1537201440%40sss.pgh.pa.us

ただし、postgresql-jdbcドライバのversion42.2.16以降、enumのEscapeSyntaxCallMode が導入され、sql文に変換される際の値を指定出来るようになったようです。EscapeSyntaxCallModeの定義を以下に引用します。
Specifies how JDBC escape call syntax is transformed into underlying SQL (CALL/SELECT), for invoking procedures or functions (requires server version >= 11), possible values: select, callIfNoReturn, call

よって、EscapeSyntaxCallModeの値をcallに設定することにより、SimpleJdbcCallを介してprocedureを呼ぶことが可能となります。具体的には、datasourceオブジェクトを生成する際にEscapeSyntaxCallModeの値をcallに設定します。以下のコード例ではapplication.propertiesのspring.datasource.urlに、EscapeSyntaxCallMode=callを書き足しました。

spring.datasource.url=jdbc:postgresql://localhost:5449/データベース名?escapeSyntaxCallMode=call

その他は冒頭に示したコードから変更することなく、SimpleJdbcCallを介してprocedureを呼ぶことがひとまず出来ました。

なお、記述の詳細については以下を参照下さい。
https://github.com/pgjdbc/pgjdbc

投稿2021/07/24 04:09

lahaina

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

bad SQL grammar [{call demo()}]

stored procedure demo に何らしかのSQL構文間違いがある、
とエラーメッセージが指摘していますので
そこを確認するしかありませんね

投稿2021/07/23 07:50

odataiki

総合スコア948

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問