浏览 5856 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-01-10
要点其实很简单,就是把在declareParameter时要先声明返回结果集参数,再声明input参数。 先看看程序吧: Sybase 存储过程 IF OBJECT_ID('dbo.sp_xx') IS NOT NULL BEGIN DROP PROCEDURE dbo.sp_xx IF OBJECT_ID('dbo.sp_xx') IS NOT NULL PRINT '<<< FAILED DROPPING PROCEDURE dbo.sp_xx >>>' ELSE PRINT '<<< DROPPED PROCEDURE dbo.sp_xx >>>' END go create proc sp_xx ( @userid int) as begin select personid, personname from person where personid = @userid select teamid, teamname from team end EXEC sp_procxmode 'dbo.sp_xx','unchained' go 正确的java调用程序如下 private class ProcWithResultSet extends StoredProcedure { public ProcWithResultSet(DataSource dataSource) { setDataSource(dataSource); setSql("sp_xx"); //declareParameter(new SqlParameter("userid", java.sql.Types.INTEGER)); //(1) //declare the first out param in the sp, the name rsPerson is the key of result map declareParameter(new SqlReturnResultSet("rsPerson", new PersonRowMapper())); //declare the second out param in the sp, the name rsTeam is the key of result map declareParameter(new SqlReturnResultSet("rsTeam", new TeamRowMapper())); //declare input params, the name userid is the IN params of the param declareParameter(new SqlParameter("userid", java.sql.Types.INTEGER)); //(2) compile(); } public Map getRsFromSP(int userID) { Map map = new HashMap(); map.put("userid", new Integer(userID)); return execute(map); } } private class PersonRowMapper implements RowMapper { public Object mapRow(ResultSet rs, int rowNum) throws SQLException { UserInfo u = new UserInfo(); u.setPersonID(rs.getInt(1)); u.setUserName(rs.getString(2)); return u; } } private class TeamRowMapper implements RowMapper { public Object mapRow(ResultSet rs, int rowNum) throws SQLException { return new PropertyValue(rs.getInt(1)+"", rs.getString(2)); } } Spring中对于jdbc 调用带有返回结果集的存储过程是用的这个方法。 /** * Extract returned ResultSets from the completed stored procedure. * @param cs JDBC wrapper for the stored procedure * @param parameters Parameter list for the stored procedure * @return Map that contains returned results */ protected Map extractReturnedResultSets(CallableStatement cs, List parameters, int updateCount) throws SQLException { Map returnedResults = new HashMap(); int rsIndex = 0; boolean moreResults; do { if (updateCount == -1) { //(3) Object param = null; if (parameters != null && parameters.size() > rsIndex) { param = parameters.get(rsIndex); //(4) } if (param instanceof SqlReturnResultSet) { SqlReturnResultSet rsParam = (SqlReturnResultSet) param; returnedResults.putAll(processResultSet(cs.getResultSet(), rsParam)); //(5) } else { logger.warn("Results returned from stored procedure but a corresponding " + "SqlOutParameter/SqlReturnResultSet parameter was not declared"); } rsIndex++; } moreResults = cs.getMoreResults(); //(6) updateCount = cs.getUpdateCount(); if (logger.isDebugEnabled()) { logger.debug("CallableStatement.getUpdateCount() returned " + updateCount); } } while (moreResults || updateCount != -1); return returnedResults; } 原因分析: 1:Sybase不支持Out 参数返回结果集。只能再Sp当中最后select column from some table 2:Sybase的JDBC Driver对于jdbc的实现比较令人费解,如果一个Sp返回多个结果集,如果不调用第一个结果集即statement.getResultSet() 那么接下来statementcs.getMoreResults()会返回False,即使有有第二个返回结果集,它一样返回false,那么Spring就会把返回结果认为是一个update的 结果,就不会对其它结果集进行处理。 3:Spring中如果jdbc返回结果集,那么程序会执行到(3)处,这里rsIndex = 0,如果输入参数声明在先,那么这里得到的将会是输入参数, (5)处的cs.getResultSet()将不会被执行,第一个ResultSet不会被处理,同时,因为(5)处没有被执行,那么(6)处会返回false,也就是解下来 的结果集不会被正确的认出来,Spring也不会去处理后续的结果集,这样就一个结果集也得不到了。 4:这里主要还是Sybase jdbcDriver在实现jdbc时有bug,但是我们只能顺着人家来,在用Spring Jdbctemplate调用时注意一下了。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |