我试图在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(); }
我尝试调用此过程时得到的错误如下
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中调用存储过程时,完全相同的代码工作正常
任何帮助是极大的赞赏
谢谢Damien
ProcedureOutputs
是interface
哪个extends
Outputs
(源).
ResultSetOutput
是interface
哪个extends
Output
(源).当你打电话getCurrent()
时Outputs
,你会得到一个Output
(来源).
基本上,您希望转换是正确的,因为您将结果转换为子接口Output
.你正在做的事情被称为垂头丧气.我们来看看案例.
您想将对象转换为另一个对象.从那时起,这可能是可能的ResultSetOutput
extends
Output
.由于可能存在向下转换,因此您不会收到编译时错误,并且在可能的情况下,例如在MySQL中调用存储过程时,向下转换将成功.但是,当无法进行向下转换时,会出现运行时异常.在我们的特定情况下,向下转换是不可能的,因为.getOutputs
返回另一个分类,可能是另一个继承分支上的子接口,如UpdateCountOutput.
Lajos对于这个沮丧的人是正确的.问题在于,你假设Output
返回的ProcedureOutputs.getCurrent()
是a ResultSetOutput
,而实际上它可能是一个UpdateCountOutput
.
实际上,Output
界面有一种方法isResultSet()
可以帮助您确定:
boolean org.hibernate.result.Output.isResultSet()
确定此返回是否为结果(可转换为
ResultSetOutput
).另一种方法是它是一个更新计数(可转换为UpdateCountOutput
).返回:
true
表示这可以安全地转换为ResultSetOutput
),否则可以转换为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
用更新计数输出做一些事情
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在这里,所以如果它返回两个我无法证实ResultSetOutput
和UpdateCountOutput
,但在不同的顺序HSQLDB,但也许你可以验证.