`
IvanLi
  • 浏览: 602727 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用Spring jdbc template调用Sybase带有返回结果集的储存过程-要点

阅读更多
google半天,没找到有人写者方面的,我就开个头吧。有不对的地方还请大侠们拍砖。
要点其实很简单,就是把在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调用时注意一下了。
分享到:
评论
1 楼 suu 2012-04-09  
写个存储过程,爆如下错误,是不是游标里的数据太多引起的?
无法执行语句。
JZ0CU: 成功调用 getMoreResult 后,只能调用一次 getUpdateCount。否则应执行方法。
SQLCODE=0,ODBC 3 状态="JZ0CU"

第 1 行,第 1 列

exec dbo.proc_getHaviorData

相关推荐

    Spring JdbcTemplate调用Oracle存储过程实现CRUD

    存储过程使用 `SYS_REFCURSOR` 输出参数将结果集返回给调用方。 `P_EMP_ADD` 存储过程用于添加新员工信息,并返回添加结果。该过程接收两个输入参数:`V_ID` 和 `V_NAME`,分别用于添加员工 ID 和姓名。存储过程...

    Spring boot+Spring JDBC Template+mysql+ sharding-j-subdb.zip

    Spring JDBC Template提供了诸如事务管理、异常转换和结果集处理等高级功能,使开发者能更专注于业务逻辑,而不是底层数据库操作。 接下来是MySQL,这是一个广泛使用的开源关系型数据库管理系统(RDBMS)。它以其性能...

    使用spring jdbc template简化jdbc数据库操作实例代码

    Spring JDBC Template是Spring... &lt;artifactId&gt;spring-jdbc &lt;version&gt;5.3.23 ``` 接下来,配置Spring JDBC Template。在Spring的配置文件(如:applicationContext.xml)中,定义一个JdbcTemplate bean: ```xml ...

    开发工具 spring-jdbc-4.3.6.RELEASE

    开发工具 spring-jdbc-4.3.6.RELEASE开发工具 spring-jdbc-4.3.6.RELEASE开发工具 spring-jdbc-4.3.6.RELEASE开发工具 spring-jdbc-4.3.6.RELEASE开发工具 spring-jdbc-4.3.6.RELEASE开发工具 spring-jdbc-4.3.6....

    spring-jdbc jar包.rar

    在项目中使用"spring-jdbc jar包",开发者需要配置DataSource,并根据需求选择使用JdbcTemplate或其他辅助类。在编写SQL时,可以使用预编译的PreparedStatement来防止SQL注入攻击。此外,还可以利用Spring的AOP...

    spring-jdbc-5.3.15-API文档-中文版.zip

    赠送jar包:spring-jdbc-5.3.15.jar; 赠送原API文档:spring-jdbc-5.3.15-javadoc.jar; 赠送源代码:spring-jdbc-5.3.15-sources.jar; 赠送Maven依赖信息文件:spring-jdbc-5.3.15.pom; 包含翻译后的API文档:...

    spring对jdbc的支持jar包

    1. **JdbcTemplate**:这是Spring JDBC的基础组件,它通过模板方法模式封装了常见的JDBC操作,如执行SQL查询、更新、存储过程等。使用JdbcTemplate,开发者无需手动管理数据库连接、预编译语句、结果集转换等细节,...

    Spring JDBC与事务管理

    (1)使用Spring JDBC实现书店的购书过程,即有如下一个BookShopDao接口,编写BookShopDaoImp类实现该接口中的所有方法,并通过JUnit测试这些方法。 (2)(2) 在BookShopDao中添加一个purchase购书方法,其操作流程是...

    Spring Data JDBC与JDBC的区别

    7. **CallableStatement**: 用于调用数据库存储过程。 8. **ResultSet**: 存储查询结果,包含多条记录,可以迭代遍历。 而Spring Data JDBC是Spring框架的一部分,它简化了数据库操作,提供了更高层次的抽象。相比...

    spring_JDBC整合包

    这个"spring_JDBC基本包"可能包含的文件有Spring框架的基础库,如spring-jdbc.jar,数据库驱动如mysql-connector-java.jar,以及其他可能需要的依赖,如commons-dbcp或HikariCP这样的连接池库。确保所有必要的库都...

    使用 Spring JDBC Template 对数据库查询(登录)和删除(maven)

    使用 Spring JDBC Template 对数据库查询(登录)和删除(maven),图文教程地址:https://blog.csdn.net/qq_40147863/article/details/86015509

    使用 Spring MVC + JDBC Template 实现筛选、检索功能(maven)

    使用 Spring MVC + JDBC Template 实现筛选、检索功能(maven),图文教程地址:https://blog.csdn.net/qq_40147863/article/details/86187642

    spring jdbc.zip

    它提供了大量的方法,用于执行SQL查询、更新、存储过程等,这些方法能够自动处理资源的关闭、异常处理以及结果集的映射。例如,我们可以通过以下方式使用JdbcTemplate执行SQL查询: ```java @Autowired private ...

    使用Spring JDBC 案例

    在本文中,我们将深入探讨如何使用Spring JDBC进行数据库操作,并结合使用不同的连接池技术,包括Spring自带的、C3P0、DBCP和Druid。此外,我们还将介绍一个自定义的行映射器工具类,它在处理数据库查询结果时能提供...

    SpringJDBC.rar_SpringJDBC_spring jdbc

    Spring JDBC是Spring框架的一个重要模块,它为Java开发者提供了与关系数据库交互的抽象层,简化了JDBC(Java Database Connectivity)的使用。本教程通过一个实际案例,将深入讲解Spring JDBC的基本概念、核心组件...

    使用Spring的JdbcTemplate调用Oracle的存储过程

    使用Spring的JdbcTemplate调用Oracle的存储过程

    SpringJDBC.rar_jdbc spring_spring jd_spring jdbc_spring使用JDBC进行数

    2. **JdbcTemplate**:这是Spring JDBC最常用的工具类,提供了大量的模板方法,用于执行SQL查询、更新、调用存储过程等操作,大大减少了手动处理结果集和异常的情况。 3. **SimpleJdbcTemplate**:这是JdbcTemplate...

    Spring JDBC相关jar包:spring_jdbc_4.0.0.zip

    在这个“spring_jdbc_4.0.0.zip”压缩包中,包含的是Spring JDBC 4.0.0版本的jar文件,即“spring-jdbc-4.0.0.jar”。 在Spring JDBC中,最重要的概念是`JdbcTemplate`。这是一个非常实用的工具类,它通过模板方法...

    Spring+Jdbc scott用户的调用存储过程

    标题中的“Spring+Jdbc scott用户的调用存储过程”涉及到的是在Java开发中使用Spring框架的JDBC模块来调用数据库的存储过程。在Java应用程序中,Spring JDBC提供了一个简单且有效的方式来处理数据库交互,包括执行...

Global site tag (gtag.js) - Google Analytics