Hsqldb - 从存储过程返回结果集

时间:2015-12-21 18:35:15

标签: java hibernate hsqldb

我正在尝试在HsqlDB中调用存储过程并返回结果集

我的存储过程如下

    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;
  /;

我用来调用此proc的Java和hibernate代码如下

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();

}

我尝试调用此proc时得到的错误如下

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中调用存储过程时,完全相同的代码正常工作

非常感谢任何帮助

由于 达明

2 个答案:

答案 0 :(得分:5)

ProcedureOutputsinterface extends Outputssource)。

ResultSetOutputinterface extends Outputsource)。 当您致电getCurrent() Outputs时,您将获得Outputsource)。

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

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

答案 1 :(得分:5)

Lajos对于这个沮丧的人是正确的。问题在于,您假设Output返回的ProcedureOutputs.getCurrent()将是ResultSetOutput,而实际上它可能是UpdateCountOutput

事实上,Output界面有一个方法isResultSet()可帮助您确定:

  

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

     

确定此返回是否为结果(可转换为ResultSetOutput)。另一种方法是它是一个更新计数(可转换为UpdateCountOutput)。

     

返回:

     

true表示可以安全地转换为ResultSetOutput),否则可以将其转换为UpdateCountOutput

为此,Outputs可以提供多个OutputOutput.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

     

使用更新计数输出执行某些操作

     

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

     

1671 [main] DEBUG org.hibernate.loader.Loader - 结果集行:0

     

1671 [main] DEBUG org.hibernate.loader.Loader - 结果行:

     

使用结果集输出执行某些操作

PS:我这里没有mysql,所以我无法确认它是否同时返回ResultSetOutputUpdateCountOutput,但顺序不同于hsqldb,但也许你可以验证它。