在 Java 中,调用 PostgreSQL 函数,为什么我收到错误消息,提示该函数不存在?
我在数据库中有这个过程:
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());
}
}
这不起作用,我收到一条错误消息,通知函数replacepagerelevance(整数,双精度)不存在。
。为什么?
生成的调用如下:SELECT ReplacePageRelevance('882','8.0')
。如果我在 pgAdmin 中执行它,它可以工作,但不能从 Java 中执行。
I have this procedure in the database:
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;
And this code that calls this function:
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());
}
}
This is not working, I'm getting an error informing that function replacepagerelevance(integer, double precision) doesn't exists.
. Why?
The generated call is this: SELECT replacePageRelevance('882','8.0')
. If I execute this in pgAdmin, it works, but not from Java.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是因为您的 PL/pgSQL 函数定义为:
REAL 是单精度浮点,但在 Java 方面,您尝试将其用作双精度,并且对于这种情况没有隐式转换。
您应该使用
CallableStatement.setFloat
用于单精度REAL
数据类型,但它并不明确,因为阅读 Java API:由于
FLOAT
是 Postgres 中DOUBLE PRECISION
的同义词,因此它的运行效果与CallableStatement.setDouble
产生错误消息(这很奇怪)。当然,您可以将函数更改为
replacePageRelevance(id INT, value DOUBLE PRECISION)
,正如我检查的那样,它与您的代码配合得很好。不过,如果您想在函数中保留
REAL
),请使用显式强制转换,如下所示:It's because your PL/pgSQL function is defined as:
REAL is a single precision floating point, but on Java side you're trying to use it as double precision and there is no implicit casting for such situation.
You should rather use
CallableStatement.setFloat
for single precisionREAL
datatype, however it's not co clear, becuase reading Java API:Since
FLOAT
is a synonym forDOUBLE PRECISION
in Postgres it runs with same effect asCallableStatement.setDouble
producing error message (that's weird).Of course you could just change your function to
replacePageRelevance(id INT, value DOUBLE PRECISION)
and as I checked it works well with your code.Nevertheless, If you want to keep
REAL
in your function), then use explicit cast like this: