从Spring调用带有多行返回的Oracle存储过程

时间:2018-11-29 20:34:06

标签: java spring oracle stored-procedures

我正在使用Java,Eclipse和Spring开发应用程序。我们有一个要使用JDBC连接的Oracle数据库。

当前,应用程序正在使用应用程序中的临时查询到数据库。这些大多数都是在我来之前由从事该项目的人员完成的。我已经决定使用存储过程是一种更好的方法。解耦以获得另一层抽象。不必每次都发送sql语句,因此带宽更少,事务处理更快。 Oracle可以对它们进行优化,而不像传统的那样。只要输入和输出不变,就可以对它们进行更改,而无需重新编译。所有这些奇妙的东西。

adhoc查询经常返回多行,并使用rowMapper和mapRow接口

 return jdbcTemplate.query(sql, new adhoc_mapper1());

class adhoc_mapper1 implements RowMapper<List<String>> {
    public List<String> mapRow(ResultSet rs, int arg1) throws SQLException{
    ArrayList<String> arr1 = new ArrayList<String>();
    arr1.add(rs.getString("OUT_POSITION_ID"));
    arr1.add(rs.getString("OUT_POSITION_TITLE_EN"));

    return arr1;
    }
}

春季临时查询

 SELECT     HR.POSITION_ID,     HR.POSITION_TITLE_EN,   HR.POSITION_TITLE_FR,   HR.SECURITY_ID,     HR.GROUP_NAME,  HR.GROUP_LEVEL,     HR.POSITION_IS_ACTIVE
    FROM HR_POSITION HR JOIN DRILL_POSITION DP ON (HR.POSITION_ID = DP.POSITION_ID) 
WHERE DP.TYPEVALUE = RECORD_TYPE;

Oracle中的被调用过程

CREATE OR REPLACE PROCEDURE DOCSADM.DRILL_RECORD_POSITION (
    RECORD_TYPE IN VARCHAR2,
    OUT_POSITION_ID OUT VARCHAR2,
    OUT_POSITION_TITLE_EN OUT VARCHAR2,
    OUT_POSITION_TITLE_FR OUT VARCHAR2,
    OUT_SECURITY_ID OUT VARCHAR2,
    OUT_GROUP_NAME OUT VARCHAR2,
    OUT_GROUP_LEVEL OUT VARCHAR2,
    OUT_POSITION_IS_ACTIVE OUT VARCHAR2
) AS
BEGIN
    SELECT  HR.POSITION_ID,     HR.POSITION_TITLE_EN,   HR.POSITION_TITLE_FR,   HR.SECURITY_ID,     HR.GROUP_NAME,  HR.GROUP_LEVEL,     HR.POSITION_IS_ACTIVE
    INTO    OUT_POSITION_ID,    OUT_POSITION_TITLE_EN,  OUT_POSITION_TITLE_FR,  OUT_SECURITY_ID,    OUT_GROUP_NAME, OUT_GROUP_LEVEL,    OUT_POSITION_IS_ACTIVE
    FROM HR_POSITION HR JOIN DRILL_POSITION DP ON (HR.POSITION_ID = DP.POSITION_ID) WHERE DP.TYPEVALUE = RECORD_TYPE;
END DRILL_RECORD_POSITION;

如您所见,该过程返回多行。我曾问过question关于如何在Oracle中查看该过程的输出的信息,但是没有成功。

由于该项目未使用被调用的过程,因此我在代码库中没有可用于工作的示例。我的一个参与另一个项目的同事使用了它们,并且很友好地向我展示了他们的示例,但遗憾的是,这没有帮助,因为它仅调用一个过程且没有任何回报。他们的整体设计也似乎有所不同。但是我看到他们正在使用SimpleJdbcCall,所以我开始在网上寻找使用它的方法。

网上的好例子,我没能上班。

我发现一些例子正在做我需要做的事情,但并不完全符合我的期望。

  1. This example遵循了我期望看到和使用的方式,只是结果只包含一行,而且我不知道如何更改映射以接受多个行。
  2. This example确实使用了返回多行的过程,但是它使用了ParameterizedBeanPropertyRowMapper并传递了一个类。
  3. This example有几种执行这些调用的方法,但是都是单行返回,但是答案注释的确表明它易于扩展为多行。但是我又无法使其工作。

我不想为每个过程或过程系列创建一个类。大多数查询最终都会在表中显示信息,因此我一直在使用2d对象来保存然后显示数据。到目前为止非常方便。我可以为每个过程创建一个映射,因为它需要完成(除非有更好的方法?),但是我不想为每个过程(有时也包括映射器)创建一个类。

我有150行失败的代码尝试,为了使问题更短,我没有列出。如果他们有帮助,那么我可以包括他们。

TL; DR 我想从Spring调用Oracle中的存储过程,该存储过程将返回多行。我只想使用调用函数,该函数要么使用RowMapper的映射方法,要么使用in函数映射。如果可能,我想避免使用数据的类结构。我希望/希望它看起来像第一个代码块一样被使用。

1 个答案:

答案 0 :(得分:0)

我的方法存在一个基本错误。我尝试返回多行的方式是错误的。正如某人在我的链接问题中指出的那样。因此,我尝试访问它的方式也是错误的。当我将返回限制为一行时,以下操作成功。

首先进口

import java.sql.Connection;
import java.sql.CallableStatement;

然后打电话

 final String procedureCall = "{call DRILL_RECORD_POSITION(?, ?, ?, ?, ?, ?, ?, ?)}";

      try (Connection connection = jdbcTemplate.getDataSource().getConnection();) 
      {
          ArrayList<String> inner = new ArrayList<String>();
          CallableStatement callableSt = connection.prepareCall(procedureCall);
          callableSt.setString(1, "D");

          callableSt.registerOutParameter(2, Types.VARCHAR);
          callableSt.registerOutParameter(3, Types.VARCHAR);
          callableSt.registerOutParameter(4, Types.VARCHAR);
          callableSt.registerOutParameter(5, Types.VARCHAR);
          callableSt.registerOutParameter(6, Types.VARCHAR);
          callableSt.registerOutParameter(7, Types.VARCHAR);
          callableSt.registerOutParameter(8, Types.VARCHAR);

          //Call Stored Procedure
          callableSt.executeUpdate();

          for (int i=2; i<9; i++)
          {
               System.out.println(callableSt.getString(i));
          }
      }catch (SQLException e) {
        e.printStackTrace();
      }

请注意,我正在尝试使用资源,因此不必担心关闭连接。

在此期间我犯的其他错误还不够?在字符串中导致无效的列索引错误。然后我犯了一个错误,那就是在我实际执行呼叫之前尝试获取信息。