简体   繁体   English

JDBC SQL 服务器存储过程,带有 ResultSet、返回值和 output 参数

[英]JDBC SQL Server Stored Procedure with ResultSet, return value, and output parameters

I am in the process of converting an application from Jython to compiled Java.我正在将应用程序从 Jython 转换为已编译的 Java。 The application uses a host of SQL Server stored procedures to do CRUD operations.该应用程序使用一个主机 SQL 服务器存储过程来做 CRUD 操作。 All of the procedures are defined with a return value that indicates status, and some output parameters used to provide feedback to the application.所有的过程都定义了一个返回值来指示状态,并且一些 output 参数用于向应用程序提供反馈。 Most of the procedures also return a result set.大多数过程还返回一个结果集。 I'm struggling with how to retrieve the return value and the result set and the output parameters.我正在努力如何检索返回值和结果集以及 output 参数。

I normally work with C# so the nuances of JDBC are new to me.我通常使用 C#,所以 JDBC 的细微差别对我来说是新的。 I've been testing with one of the procedures that does an insert to the database and then does a select on the inserted object.我一直在测试其中一个插入数据库的过程,然后在插入的 object 上执行 select。

Here's a simplified example procedure just to use for the purpose of illustration .这是一个简化的示例过程,仅用于说明目的 The actual procedures are more complex than this.实际程序比这更复杂。

CREATE PROCEDURE [dbo].[sp_Thing_Add]
(
   @Name NVARCHAR(50),
   @Description NVARCHAR(100),
   @ResultMessage NVARCHAR(200) = N'' OUTPUT
)
AS
BEGIN
   SET NOCOUNT ON
   
   DECLARE @Result INT = -1
   DECLARE @ResultMessage = 'Procedure incomplete'
   
   BEGIN TRY
      INSERT INTO Things (Name, Description) VALUES (@Name, @Description)

      SELECT * FROM Things WHERE ThingID = SCOPE_IDENTITY()
   END TRY
   BEGIN CATCH
      SELECT @Result = CASE WHEN ERROR_NUMBER() <> 0 THEN ERROR_NUMBER() ELSE 1 END,
         @ResultMessage = ERROR_MESSAGE()
      GOTO EXIT_SUB
   END CATCH
SUCCESS:
   SET @Result = 0
   SET @ResultMessage = N'Procedure completed successfully'
   RETURN @Result
EXIT_SUB:
   IF @Result <> 0
   BEGIN
   -- Do some error handling stuff
   END
   RETURN @Result

      

I can successfully retrieve the ResultSet using the following code.我可以使用以下代码成功检索 ResultSet。

var conn = myConnectionProvider.getConnection();
String sql = "{? = call dbo.sp_Thing_Add(?, ?, ?)}"

call = conn.prepareCall(sql);
call.registerOutParameter(1, TYPES.Integer); // Return value
call.setString("Name", thing.getName());
call.setString("Description", thing.getDescription());
call.registerOutParameter("ResultMessage", TYPES.NVARCHAR);
ResultSet rs = call.executeQuery();

// Try to get the return value. This appears to close the ResultSet and prevents data retrieval.
//int returnValue = call.getInt(1);
// Normally there'd be a check here to make sure things executed properly, 
// and if necessary the output parameter(s) may also be leveraged

if (rs.next()) {
   thing.setId(rs.getLong("ThingID"));
   // Other stuff actually happens here too...
}

If I try retrieving the return value using the line that's commented out, I get an error stating that the ResultSet is closed.如果我尝试使用已注释掉的行检索返回值,则会收到一条错误消息,指出 ResultSet 已关闭。

com.microsoft.sqlserver.jdbc.SQLServerException: The result set is closed. com.microsoft.sqlserver.jdbc.SQLServerException:结果集已关闭。

I've been through the documentation and have seen how to do return values, output parameters, and result sets.我浏览了文档并了解了如何执行返回值、output 参数和结果集。 But how can I leverage all 3?但是我怎样才能利用这三个?

Given the order of processing in your stored procedure (insert, select, then populate result parameters), you need to process the result set before you retrieve the return value with CallableStatement.getXXX .给定存储过程中的处理顺序(插入 select,然后填充结果参数),您需要在使用CallableStatement.getXXX检索返回值之前处理结果集。

The output is in the ResultSet rs retrieved from executeQuery() . output 位于从executeQuery()检索到的ResultSet rs中。

You may want to use the excute method as such:您可能希望这样使用 excute 方法:

    call.execute();
    String returnValue = call.getString("ResultMessage");

You also want to map correctly to the output type.您还希望将 map 正确地转换为 output 类型。

Your connection got closed once the execute query is executed.一旦执行查询执行,您的连接就会关闭。 Basically mysql jdbc connection extends to AutoCloseable implicitly.基本上 mysql jdbc 连接隐式扩展到 AutoCloseable。 Since your result is only entity from procedure,please get the value by index 0 and do a proper index out of bound exception handling.由于您的结果只是过程中的实体,请通过索引 0 获取值并进行适当的索引超出范围异常处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM