在 Java 中,调用 PostgreSQL 函数,为啥我收到一个错误,通知该函数不存在?
Posted
技术标签:
【中文标题】在 Java 中,调用 PostgreSQL 函数,为啥我收到一个错误,通知该函数不存在?【英文标题】:In Java, calling a PostgreSQL function, why I'm getting an error informing that the function doesn't exists?在 Java 中,调用 PostgreSQL 函数,为什么我收到一个错误,通知该函数不存在? 【发布时间】:2011-09-01 17:16:51 【问题描述】:我在数据库中有这个程序:
CREATE OR REPLACE FUNCTION replacePageRelevance(id INT, value REAL) RETURNS VOID AS $$
BEGIN
INSERT INTO pageRelevance VALUES (id,value);
EXCEPTION WHEN unique_violation THEN
UPDATE pageRelevance SET relevance = value WHERE pageId = id;
END
$$
LANGUAGE plpgsql;
以及调用此函数的这段代码:
try (CallableStatement cstm = conn.prepareCall(PAGE_RELEVANCE_SQL))
for (Map.Entry<Integer, Double> entry : weightMap.entrySet())
cstm.setInt(1, entry.getKey());
cstm.setDouble(2, entry.getValue());
cstm.addBatch();
cstm.executeBatch();
catch (SQLException e)
LOGGER.error("Error discovering pages relevance: " + e.getNextException());
这不起作用,我收到一条错误消息,通知 function replacepagerelevance(integer, double precision) doesn't exists.
。为什么?
生成的调用是这样的:SELECT replacePageRelevance('882','8.0')
。如果我在 pgAdmin 中执行它,它可以工作,但不是来自 Java。
【问题讨论】:
【参考方案1】:这是因为您的 PL/pgSQL 函数定义为:
replacePageRelevance(id INT, value REAL)
REAL 是单精度浮点数,但在 Java 端,您尝试将其用作双精度,并且没有针对这种情况的隐式转换。
您应该使用 CallableStatement.setFloat
单精度 REAL
数据类型,但它并不清楚,因为阅读 Java API:
将指定参数设置为给定的 Java 浮点值。这 驱动程序在将其发送到 数据库。
由于 FLOAT
在 Postgres 中是 DOUBLE PRECISION
的同义词,它的运行效果与 CallableStatement.setDouble
产生错误消息的效果相同(这很奇怪)。
当然,您可以将您的函数更改为 replacePageRelevance(id INT, value DOUBLE PRECISION)
,并且我检查过它适用于您的代码。
尽管如此,如果你想在你的函数中保留REAL
),那么使用这样的显式转换:
String PAGE_RELEVANCE_SQL = "call replacePageRelevance(?, ?::real)";
【讨论】:
什么PostgreSQL类型兼容双精度? @Renato:就double precision
感谢您的回答和解释。我现在正在使用转换,因为我不需要太多的精度以上是关于在 Java 中,调用 PostgreSQL 函数,为啥我收到一个错误,通知该函数不存在?的主要内容,如果未能解决你的问题,请参考以下文章
Postgresql 11:存储过程调用错误 - 要调用过程,请使用 CALL、Java