Hsqldb - Return 来自存储过程的结果集

Hsqldb - Return a Result Set from Stored Proc

我正在尝试调用 HsqlDB 中的存储过程和 return 结果集

我的存储过程如下

    CREATE PROCEDURE p_getTeamTasksForLastXDays(IN teamId BIGINT, IN numberOfDays BIGINT) READS SQL DATA
  DYNAMIC RESULT SETS 1
  BEGIN ATOMIC
   declare curs cursor for select taskId, taskName from V_TASK_DETAILS;
   open curs;
  END;
  /;

我用来调用这个过程的 Java 和休眠代码如下

public void getTaskExecutionLogs(Long teamId, Long numberOfDays) {
        LOG.info("Entered getTaskExecutionLogs Method - teamId:{}, numberOfDays: {}", teamId, numberOfDays);

        ProcedureCall procedureCall = currentSession().createStoredProcedureCall("p_getTeamTasksForLastXDays");
        procedureCall.registerParameter( TEAM_ID, Long.class, ParameterMode.IN ).bindValue( teamId );
        procedureCall.registerParameter( NUMBER_OF_DAYS, Long.class, ParameterMode.IN ).bindValue( numberOfDays );

        ProcedureOutputs outputs = procedureCall.getOutputs();
        ResultSetOutput resultSetOutput = (ResultSetOutput) outputs.getCurrent();

        List resultSetList = resultSetOutput.getResultList();

}

当我试图调用这个过程时得到的错误如下

java.lang.ClassCastException: org.hibernate.result.internal.UpdateCountOutputImpl cannot be cast to org.hibernate.result.ResultSetOutput
    at com.mct.dao.database.impl.TaskDetailsDAOImpl.getTaskExecutionLogs(TaskDetailsDAOImpl.java:229)

当我尝试在 MySql

中调用存储过程时,完全相同的代码工作正常

非常感谢任何帮助

谢谢 达米安

ProcedureOutputsinterface 其中 extends Outputs (source).

ResultSetOutputinterface 其中 extends Output (source)。 当你调用 OutputsgetCurrent() 时,你会得到一个 Output (source).

基本上,您期望转换是正确的,因为您将结果转换为 Output 的子接口。你正在做的事情叫做downcast。让我们看看案例。

您想将一个对象转换为另一个对象。向下转换可能是可能的,因为 ResultSetOutput extends Output。由于向下转换可能是可能的,因此不会出现编译时错误,并且在可能的情况下,例如在 MySQL 中调用存储过程时,向下转换会成功。但是,当无法进行向下转换时,您会得到一个运行时异常。在我们的特定情况下,向下转换是不可能的,因为 .getOutputs returns 另一个分类,可能是另一个继承分支上的子接口,如 UpdateCountOutput.

Lajos 对沮丧的看法是正确的。问题是您在假设 ProcedureOutputs.getCurrent() 返回的 Output 将是 ResultSetOutput 的情况下进行编码,而实际上,它可能是 UpdateCountOutput.

其实Output接口有一个方法isResultSet()可以帮你判断:

boolean org.hibernate.result.Output.isResultSet()

Determine if this return is a result (castable to ResultSetOutput). The alternative is that it is an update count (castable to UpdateCountOutput).

Returns:

true indicates that this can be safely cast to ResultSetOutput), other wise it can be cast to UpdateCountOutput.

除此之外,Outputs可以传递多个Output并且Output.getCurrent()的状态由Output.goToNext()控制。

因此,为了正确处理多个结果,您必须使用如下内容获取输出:

ProcedureOutputs outputs = procedureCall.getOutputs();

do {
    Output current = outputs.getCurrent();

    if (current.isResultSet()) {
        ResultSetOutput resultSetOutput = (ResultSetOutput) current;
        System.out.println("do something with result set output");
    } else {
        UpdateCountOutput updateCountOutput = (UpdateCountOutput) current;
        System.out.println("do something with update count output");
    }            
} while (outputs.goToNext());

outputs.release();

在我的测试中我得到:

1647 [main] DEBUG org.hibernate.SQL - {call p_getTeamTasksForLastXDays(?,?)}

Hibernate: {call p_getTeamTasksForLastXDays(?,?)}

1668 [main] DEBUG org.hibernate.result.internal.OutputsImpl - Building Return [isResultSet=false, updateCount=0, extendedReturn=false

do something with update count output

1669 [main] DEBUG org.hibernate.result.internal.OutputsImpl - Building Return [isResultSet=true, updateCount=-1, extendedReturn=false

1671 [main] DEBUG org.hibernate.loader.Loader - Result set row: 0

1671 [main] DEBUG org.hibernate.loader.Loader - Result row:

do something with result set output

PS:我这里没有mysql,所以我无法确认它是否returns同时ResultSetOutputUpdateCountOutput但在不同的order 比 hsqldb,但也许你可以验证一下。