【问题标题】:How to use jmeter to test an Oracle Stored Procedure with sys_refcursor return type?如何使用 jmeter 测试具有 sys_refcursor 返回类型的 Oracle 存储过程?
【发布时间】:2012-10-13 03:08:42
【问题描述】:

我想用 jmeter 测试一个 Oracle 存储过程。除了参数我什么都做了。

这是我的 SQL 查询:

声明 outinfo varchar2(20); outtable sys_refcursor; 开始 {调用 RK_JSCX(?,?)}; 结束;

Oracle中的outtable是一个游标。我使用resultSet将它包含在java中。但是,无论我在参数类型中设置什么,它都表示无效类型。

样品开始时间:2012-10-25 16:06:41 CST 加载时间:0 延迟:0 字节大小:25 标头大小(以字节为单位):0 正文大小(以字节为单位):25 样本数:1 错误计数:1 响应码:空 0 响应消息:java.sql.SQLException:无效数据类型:游标

响应标头: oracle.jdbc.driver.T4CConnection@58ba09

SampleResult 字段: 内容类型:文本/纯文本 数据编码:UTF-8

如何解决? 谢谢!

这是我的java代码:

public String RK_JSCX() throws Exception {

    RK_JSCX_Response response = null;
    List<RK_JSCX_Outtable> list = null;
    Connection con = null;
    CallableStatement cs = null;
    ResultSet rs = null;
    String sql = null; 
    try {
        sql = "{call RK_JSCX(?,?)}";
        con = ConnectionUtils.getInstance().getConnect();

        if (con.isClosed()) {
            throw new IllegalStateException("ERROR.THE   CONNECTION   ISCLOSED");
        }

        cs = con.prepareCall(sql);
        cs.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
        cs.registerOutParameter(2, Types.VARCHAR);

        cs.execute();

        rs = (ResultSet) cs.getObject(1);
        list = new ArrayList<RK_JSCX_Outtable>();
        while (rs.next()) {

            RK_JSCX_Outtable out = new RK_JSCX_Outtable(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getInt(5), rs.getString(6));

            list.add(out);
        }
        String outInfo = cs.getString(2);
        response = new RK_JSCX_Response(list, outInfo);

    } catch (SQLException e) {

        e.printStackTrace();

    } catch (Exception e) {
        e.printStackTrace();

    }finally {

        try {
            if (rs != null) {
                rs.close();
                if (cs != null) {
                    cs.close();
                }
                if (con != null) {
                    con.close();
                }
            }
        } catch (SQLException e) {

            System.out.println("Exception2");
            e.printStackTrace();
        }
    }
    return JSON.toJSONString(response);
}

【问题讨论】:

  • 你能把你的代码贴在你从java调用你的oracle存储过程的地方吗?
  • 所以你在这里遇到异常cs = con.prepareCall(sql); cs.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR); cs.registerOutParameter(2, Types.VARCHAR); 你的程序接收到一个参数对吗?
  • 当您从 sqlplus 或后端执行此操作时会返回什么? declare outinfo varchar2(20); outtable sys_refcursor; begin {call RK_JSCX(?,?)}; end;
  • 当我运行 java 应用程序时一切正常。我的程序接收两个参数。一个是游标,另一个是 varchar。
  • 我还没有在PL/SQL中执行这段代码。

标签: oracle testing stored-procedures jmeter sys-refcursor


【解决方案1】:

这是怎么做的:

  • SQL 查询:调用 RK_JSCX(?,?)

  • 参数值:OUT、OUT

  • 参数类型:OUT -10,OUT VARCHAR

    -10 是 OracleTypes.CURSOR 的 int 值

  • 变量名:游标、outInfo

     Names are what you want
    

JMeter 允许使用比 java.sql.Types 常量更多的类型,在这种情况下,您不使用常量名称,而是使用常量的整数值。

文档已经澄清(在下一个 JMeter 版本中),请参阅:

【讨论】:

  • 感谢您的建议。我意识到类型错误。可以修复吗?您的意思是我应该使用其他采样器吗?我阅读了 JSR223 Sampler 的文档,但我仍然不知道如何做吧。
  • 您好,是的,这就是我的建议。在java中对jdbc调用进行编码,通过jsr223采样器调用。使用 OracleTypes.CURSOR 和 OracleCallableStatement 搜索关于 SO 的示例。
  • 实际上我最初的答案是错误的,我更新并测试了它。
  • 谢谢。我得到了游标,但是值是像oracle.jdbc.driver.OracleResultSetImpl@b2d7e8这样的对象ID。我也想得到游标中的值。
  • 您必须在 beanshell 采样器中处理这个。
【解决方案2】:

尝试以下更改

将调用过程的语法改为

cs = con.prepareCall("BEGIN RK_JSCX(?, ?); END;");

而且我相信您的第一个 OUT 参数是 VARCHAR2 对吗?所以

cs.registerOutParameter(1, Types.VARCHAR);

那么 使用以下内容来转换 CallableStatement

rs = ((OracleCallableStatement)cs).getCursor(2);

更新 1

我已更改您的程序以演示工作版本

程序

CREATE OR REPLACE PROCEDURE rk_jscx (outtable   OUT sys_refcursor,
                                                 outinfo    OUT VARCHAR2
                                                )
AS
BEGIN
    OPEN outtable FOR
        SELECT  SYSDATE
          FROM  DUAL;

    outinfo := 1;
EXCEPTION
    WHEN NO_DATA_FOUND
    THEN
        outinfo := 2;
        ROLLBACK;
END rk_jscx;

Java 代码

CallableStatement stmt = conn.prepareCall("BEGIN rk_jscx(?, ?); END;");
 stmt.registerOutParameter(1, OracleTypes.CURSOR); 
 stmt.registerOutParameter(2, Types.VARCHAR);
 stmt.execute();
      ResultSet rs = ((OracleCallableStatement)stmt).getCursor(1);
      while (rs.next()) {
        System.out.println(rs.getDate("sysdate")); 
      }

上面打印2012-10-23

同时检查您的 jdbc 驱动程序

【讨论】:

  • 有一个 ClassCastException。因为 con.prepareCall() 返回一个 CallableStatement 并且不能强制转换为 oracle.jdbc.OracleCallableStatement
  • 你在哪里得到 ClassCastException?在这一行rs = ((OracleCallableStatement)cs).getCursor(2); ?
  • 是的,我在这一行得到 ClassCastException。
  • 试试cs = (CallableStatement)con.prepareCall();
  • 更多信息您可以找到here
猜你喜欢
  • 2011-10-10
  • 1970-01-01
  • 2018-09-03
  • 1970-01-01
  • 2017-08-18
  • 2010-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多