【问题标题】:How to call PostgreSQL procedure in Java?如何在 Java 中调用 PostgreSQL 过程?
【发布时间】:2016-02-18 07:14:28
【问题描述】:

如何在Java中进行这样的查询并得到结果:

SELECT filedata.num,st_area(ST_Difference(ST_TRANSFORM(filedata.the_geom,70066),filedata_temp.the_geom))
FROM filedata, filedata_temp
Where filedata.num=filedata_temp.num

或者,我认为如果我根据这个查询在 Postgres 中创建过程会更好。

CREATE OR REPLACE FUNCTION get_geom_difference()
RETURNS void AS
$$
BEGIN
SELECT filedata.num,st_area(ST_Difference(ST_TRANSFORM(filedata.the_geom,70066),filedata_temp.the_geom))
FROM filedata, filedata_temp
Where filedata.num=filedata_temp.num

end;
$$
LANGUAGE 'plpgsql'

并称之为

Connection ce_proc= null;
ce_proc = DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgis","postgres","123456");
java.sql.CallableStatement proc =  ce_proc.prepareCall("{get_geom_difference()}");
proc.execute();
proc.close();
ce_proc.close();

但是如何在 Java 中从这个过程中得到结果呢?

更新

我试过这个SP

DROP FUNCTION get_geom_difference();

CREATE OR REPLACE FUNCTION get_geom_difference()
RETURNS integer AS
$$
DECLARE

tt integer;
BEGIN
SELECT filedata.num INTO tt
FROM filedata
Where filedata.num=1;
RETURN tt;

END;
$$
LANGUAGE 'plpgsql'

并调用

Class.forName("org.postgresql.Driver");
Connection connect= null;
connect = DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgis","postgres","123456");
java.sql.CallableStatement proc =  connect.prepareCall("{?=call get_geom_difference()}");
proc.registerOutParameter(1, java.sql.Types.INTEGER);
proc.executeQuery(); 
ResultSet results = (ResultSet) proc.getObject(1);

得到一个错误:

org.apache.jasper.JasperException:发生异常处理 JSP 页面 /commit_changes.jsp 在第 25 行in lineproc.executeQuery();

根本原因 javax.servlet.ServletException: org.postgresql.util.PSQLException:没有返回结果 查询

但是查询

SELECT filedata.num 
FROM filedata
Where filedata.num=1;

返回1

哪里出错了?

【问题讨论】:

  • psql 中的 SELECT get_geom_difference() 怎么样?你在那里得到结果吗?如果是这样,如果为了测试,您使用带有 SELECT get_geom_difference() 而不是 {call} 语法的传统 JDBC 查询语法呢?
  • 如果您在所有这些答案之后仍然卡住,请首先提供应该在这里开始的信息:正在使用的软件的版本号(一个非常旧的 PostgreSQL 版本,没有预装的过程语言plpgsql,可能是问题),表filedata的表定义(我的回答中提到的数据类型不匹配可能是一个问题)。

标签: java postgresql


【解决方案1】:

您可以在很大程度上简化该功能。 (为了这个问题,保持简单的功能。)

CREATE OR REPLACE FUNCTION get_geom_difference()
   RETURNS integer AS
$BODY$
   SELECT num
   FROM   filedata
   WHERE  num = 1 
   LIMIT  1;  -- needed if there can be more than one rows with num = 1
$BODY$    LANGUAGE SQL;

尽管从技术上讲,您在问题中的内容也可以使用 - 只要数据类型匹配。可以?列filedata.numinteger 类型吗?这就是我从示例中收集到的信息。在your other question 上,由于缺乏信息,我假设numeric。其中至少有一个会失败。

如果函数的返回类型与返回值不匹配,您会从 PostgreSQL 函数中得到一个错误。如果配置正确,在这种情况下,您的 PostgreSQL 日志将包含详细的错误消息。

当你在 PostgreSQL 中创建上述函数然后调用时,你看到了什么:

SELECT get_geom_difference(1);

来自psql。 (最好在同一个会话中排除数据库、端口、服务器或用户的混合。)

调用一个带有一个参数并返回一个标量值的简单函数似乎很简单。 Chapter 6.1 of the PostgreSQL JDBC manual 有一个完整的示例,它似乎与您的问题完全一致(不过,我的专长是 Postgres 而不是 JDBC)。

【讨论】:

    【解决方案2】:

    CallableStatement 有很多不同的构造函数,但 only two of them let you get results back

    ResultSetCallableStatement.executeQuery() 返回。上面的链接中有一个很好的完整示例。

    我不知道从CallableStatement 返回标量结果是否合法。不过,我希望 PgJDBC 将其转换为一行的行集,所以它应该工作。

    【讨论】:

    • CallableStatement.executeQuery()不帮我,你能看看问题更新吗?
    【解决方案3】:

    您的查询示例很典型。所以你需要的是

    Java Database Connectivity (JDBC)

    所有需要的东西都在包java.sql

    所以在这一点上,我建议您阅读一些教程,如果您有一些特殊问题,请在 SO 上写下它。

    【讨论】:

      【解决方案4】:

      您将需要 JDBC 来执行此操作。您应该可以找到所有 JDBC 相关信息here

      查看here,获取有关如何将 Java 应用程序连接到 PostgreSQL 的更详细教程。

      【讨论】:

      • 当这个问题被标记为 PostgreSQL 时,你为什么要链接到 Oracle 文档。我觉得PostgreSQL JDBC docs 更合适。
      • @ErwinBrandstetter:我发布的链接是 Oracle(以前是 Sun)的 JDBC 教程。它应该是独立于数据库的,并且应该涵盖基础知识。我已经包含了一个链接,该链接应该让 OP 更直接地了解他/她所追求的目标。
      • 现在这样说才有意义。 :)
      【解决方案5】:

      适用于 100% java 7 和 postgres pgadmin 2016,使用 createNativeQuery 在您的事务中写下这个 并更改 myschema.mymethodThatReturnASelect

      为你的函数的方案和名称。

      @Override
          public List<ViewFormulario> listarFormulario(Long idUsuario) {
              List<ViewFormulario> list =null;
              try {
                  Query q = em.createNativeQuery("SELECT * FROM myschema.mymethodThatReturnASelect(?);");
                  q.setParameter(1, idUsuario);
      
                   List<Object[]> listObject = (List<Object[]>) q.getResultList();
                  if (listObject != null && !listObject.isEmpty()) {
                      list = new ArrayList<>();
                      for (Object o[] : listObject) {
                          ViewFormulario c = new ViewFormulario();
                          c.setIdProyecto(o[0] != null ? Long.valueOf(o[0].toString()) : -1L);
      

      ...等等...等等。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-07
        • 2012-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-18
        相关资源
        最近更新 更多