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

Spring JDBC调用存储过程的几种情况

阅读更多
注入spring jdbc,参见:http://godandghost.iteye.com/admin/blogs/1724763

1. 存储过程中各个出入参都是基本类型时:
PROCEDURE p_get_province
(
    iv_code                 VARCHAR2,  --字符串类型
    in_staff_role           NUMBER,    --数字类型
    in_provincial_id        NUMBER,    
    iv_m_id                 VARCHAR2,
    ocur_exec_status        OUT pkg_ref_cursor.gcur_record_set, --游标类型
    ocur_province           OUT pkg_ref_cursor.gcur_record_set  --游标类型
);


public static List getProvice(final Map<String, String> paramMap) throws Exception
{
	try {
		List list = template.execute(new ConnectionCallback<List>()
		{
			@Override
			public List doInConnection(Connection conn)
					throws SQLException, DataAccessException
			{
				CallableStatement call = conn.prepareCall("call p_get_province(?,?,?,?,?,?)");
				call.setString("iv_code", paramMap.get("Report_Id"));
				if (StringUtils.isNotBlank(paramMap.get("Role"))) {
					call.setInt("in_staff_role", Integer.parseInt(paramMap.get("Role")));
				} else {
					call.setString("in_staff_role", null);
				}
				if (StringUtils.isNotBlank(paramMap.get("ProvinceId"))) {
					call.setInt("in_provincial_id", Integer.parseInt(paramMap.get("ProvinceId")));
				} else {
					call.setString("in_provincial_id", null);
				}
				call.setString("iv_m_id", paramMap.get("mId"));
				call.registerOutParameter("ocur_exec_status", OracleTypes.CURSOR);
				call.registerOutParameter("ocur_province", OracleTypes.CURSOR);
				DataSourceUtils.applyTimeout(call, template.getDataSource(), 30);// 30秒超时
				call.execute();

				ResultSet rs = (ResultSet) call.getObject("ocur_exec_status");
				int status = 0;
				String info = "";
				while (rs.next()) {
					status = rs.getInt("Exec_Status");
					info = rs.getString("Exec_info");
				}
				rs.close();
				if (status == 0) {
					List<MyObject> provinceList = new ArrayList<MyObject>();
					ResultSet rs1 = (ResultSet) call.getObject("ocur_province");
					while (rs1.next()) {
						MyObject mo = new MyObject();
						mo.setValue(rs1.getString("province_value"));
						mo.setText(rs1.getString("province"));
						provinceList.add(mo);
					}
					rs1.close();
					return provinceList;
				} else {
					return null;
				}
			}
		});
		return list;
	}
	catch (DataAccessException e) {
		throw e;
	}
	catch (Exception e) {
		throw e;
	}
}


2.存储过程中有自定义struct时
Struct类型声明:
CREATE OR REPLACE TYPE header_struct as object
(
	w_id          varchar2(8),
	a_time        date,
	b_time        date,
	token         varchar2(20)
)

create or replace type Report_List as varray(2000) of REPORT_STRUCT

create or replace type REPORT_STRUCT as object(
	REQUEST_ID	NUMBER(10),
	STATUS		NUMBER(3),
	FILENAME		VARCHAR2(200),
	DESCRIPTION	VARCHAR2(201),
	REQUESTDATETIME	DATE
)

CREATE OR REPLACE TYPE ERROR_MESSAGE_STRUCT as object
(
    error_type         number(3),
    error_code         number(10),
    message      	   varchar2(255)
)

存储过程声明:
CREATE OR REPLACE PROCEDURE get_report_list
(
	iv_header               IN header_struct,
	iv_function_name        IN VARCHAR2,
	iv_report_date 			IN DATE,
	ov_report_list   		OUT report_list,
	ov_error_message        OUT error_message_struct
)

Java代码写法:
public static Object[] getReportResultList(final Header header,
			final String functionName, final Date dateTime)
{
	try {
		return template.execute(new ConnectionCallback<Object[]>()
		{
			@Override
			public Object[] doInConnection(Connection conn) throws SQLException, DataAccessException
			{
				Connection con = conn.getMetaData().getConnection();// 此处需要将connection类型转换一下
				OracleCallableStatement call = (OracleCallableStatement) con
						.prepareCall("call get_report_list(?,?,?,?,?)");
				
				// 存储过程第一个参数
				oracle.sql.STRUCT headerStruct = getHeaderStruct(header, con);
				// 声明存储过程的入参
				call.setSTRUCT(1, headerStruct);// 参数类型是Struct
				call.setString(2, functionName);// 参数类型是String
				call.setDate(3, dateTime);
				// 声明存储过程的出参
				call.registerOutParameter(4, OracleTypes.ARRAY, "REPORT_LIST");// REPORT_LIST必须大写
				call.registerOutParameter(5, OracleTypes.STRUCT, "ERROR_MESSAGE_STRUCT");// ERROR_MESSAGE_STRUCT必须大写

				DataSourceUtils.applyTimeout(call, sbcTemplate.getDataSource(), 30);
				call.execute();
				
				// 出参第一个结构体是一个Struct的Array
				oracle.sql.ARRAY array = call.getARRAY(4);
				List<ReportResult> resultList = new ArrayList<ReportResult>();
				if (array != null) {
					Datum[] data = array.getOracleArray();
					for (Datum datum : data) {
						STRUCT struct = (STRUCT) datum;
						Datum[] datas = struct.getOracleAttributes();
						
						int requestId = 0;
						int status = 0;
						String fileName = "";
						String description = "";
						NUMBER requestIdNum = (NUMBER) datas[0];
						if (requestIdNum != null) {
							requestId = requestIdNum.bigIntegerValue().intValue();
						}
						NUMBER statusNum = (NUMBER) datas[1];
						if (statusNum != null) {
							status = statusNum.bigIntegerValue().intValue();
						}
						
						try {
							if (datas[2] != null) {
								fileName = new String(datas[2].getBytes(), "GBK");
							}
							if (datas[3] != null) {
								description = new String(datas[3].getBytes(), "GBK");
							}
						}
						catch (UnsupportedEncodingException e) {
							logger.warn("不支持的字符编码", e);
						}
						oracle.sql.DATE requestDate = (oracle.sql.DATE) datas[4];
						java.sql.Timestamp date = null;
						if (requestDate != null) {
							date = requestDate.timestampValue();
						}
						
						ReportResult rr = new ReportResult(requestId,
								status, fileName, description, date);
						resultList.add(rr);
					}
				} else {
					System.out.println("空");
				}
				// 第二个结构体errormessage
				STRUCT errorMsgStruct = call.getSTRUCT(5);
				ErrorMessage em = new ErrorMessage();
				if (errorMsgStruct != null) {
					em = initErrorMessage(errorMsgStruct);
				}
con.close();
				return new Object[] { resultList, em };
			}
		});
	}
	catch (Exception e) {
		throw e;
	}
}

private static STRUCT getHeaderStruct(Header header, Connection con)
			throws SQLException
{
	java.sql.Timestamp aTime = null;
	java.sql.Timestamp bTime = null;
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	try {
		java.util.Date aTimeUtil = sdf.parse(header.getaTime());
		aTime = new java.sql.Timestamp(aTimeUtil.getTime());
	}
	catch (ParseException e) {
		logger.note("aTime时间转换发生错误", e);
	}
	try {
		java.util.Date bTimeUtil = sdf.parse(header.getbTime());
		bTime = new java.sql.Timestamp(bTimeUtil.getTime());
	}
	catch (ParseException e) {
		logger.note("bTime时间转换发生错误", e);
	}

	Object[] head = { header.getWitnessID(), bTime, aTime,
			header.getToken() };
	oracle.sql.StructDescriptor headerDesc = oracle.sql.StructDescriptor.createDescriptor("HEADER_STRUCT", con);// HEADER_STRUCT必须大写
	oracle.sql.STRUCT headerStruct = new oracle.sql.STRUCT(headerDesc, con, head);
	return headerStruct;
}

private static ErrorMessage initErrorMessage(STRUCT errorMsgStruct)
{
	try {
		Datum[] datas = errorMsgStruct.getOracleAttributes();
		
		int errorType = 0;
		int errorCode = 0;
		String errorMsg = "";
		
		NUMBER errorTypeNum = (NUMBER) datas[0];
		if (errorTypeNum != null) {
			errorType = errorTypeNum.bigIntegerValue().intValue();
		}
		NUMBER errorCodeNum = (NUMBER) datas[1];
		if (errorCodeNum != null) {
			errorCode = errorCodeNum.bigIntegerValue().intValue();
		}
		try {
			if (datas[2] != null) {
				errorMsg = new String(datas[2].getBytes(), "GBK");
			}
		}
		catch (UnsupportedEncodingException e) {
			logger.warn("不支持的字符编码", e);
		}
		ErrorMessage em = new ErrorMessage(errorCode, errorType, errorMsg);
		return em;
	}
	catch (SQLException e) {
		return null;
	}
}


需要注意的是,oracle的驱动包与字符集包必须对应,否则一旦Struct结构体中有字符串(无论是不是中文)都是乱码,导致Struct结构体初始化失败。我用的oracle驱动包是ojdbc6.jar,就必须用与其对应的orai18n.jar。关于乱码问题可以参见:http://blog.csdn.net/hzw2312/article/details/8444462

另注:
当使用Connection con = conn.getMetaData().getConnection();转换数据库连接时,此连接相当于新建了一个连接,不受Spring JDBC控制,不会自动回收。所以在程序最后需要手动关闭:con.close();
分享到:
评论

相关推荐

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

    Spring JDBC是Spring框架的一个核心模块,它为Java数据库连接(JDBC)提供了一种抽象层,使得开发者可以更轻松地处理数据库操作。Spring JDBC模块的主要目标是减少对JDBC API的直接依赖,通过提供一种更加高级、易于...

    java开发之SSS整合教程.继SSH,SSM之后,spring全家桶SSS问世,数据库采用SpringJDBC

    "Spring JDBC入门 - SangS - 博客园.url" 和 "SpringJdbc的几种不同的用法 - 低调开发 - ITeye技术网站.url" 可能包含了一些关于如何使用SpringJDBC的基本教程和高级技巧,包括批处理操作、动态SQL和自定义SQL查询等...

    spring jdbc

    6. **JDBC 模板扩展**:除了 JdbcTemplate,Spring 还提供了一个更高级的接口——SimpleJdbcInsert 和 SimpleJdbcCall,它们分别简化了插入操作和存储过程的调用。 7. **异常处理**:Spring JDBC 把 SQL 异常翻译成...

    Spring mvc + Spring + Spring jdbc 整合 demo.rar

    【标题】"Spring mvc + Spring + Spring jdbc 整合 demo.rar" 提供了一个整合了Spring MVC、Spring和Spring JDBC的示例项目。这个压缩包包含了一整套使用Java EE技术栈开发的Web应用程序,主要关注于后端数据处理和...

    hiberate SQL Server 2000 存储过程.pdf

    示例代码展示了如何在Hibernate中使用JDBC调用存储过程: ```java Session session = HibernateSessionFactory.currentSession(); Connection conn = session.connection(); Transaction tx = session.begin...

    Spring jdbc中数据库操作对象化模型的实例详解

    Spring JDBC提供了几种不同的查询实现: - **GenericSqlQuery**:通用查询,适用于一般的SQL查询。 - **UpdatableSqlQuery**:除了返回查询结果外,还可以更新与查询结果关联的数据。 - **...

    SpringJDBC:Spring中的数据库操作

    Spring JDBC是Spring框架的一部分,它提供了一种抽象层,使得我们能够更方便地使用Java的JDBC(Java Database Connectivity)来处理数据库操作。这个模块的主要目标是简化数据库访问,同时保持JDBC的强大功能,避免...

    JDBC培训资料java连接数据库

    高级主题可能包括批处理、预编译的PreparedStatement、存储过程调用、事务管理、异常处理、连接池的使用以及JDBC的性能优化。 5. **JDBC 2.0核心功能和扩展**: JDBC 2.0引入了一些新特性,如CallableStatement...

    详解poi+springmvc+springjdbc导入导出excel实例

    本文将围绕“poi+springmvc+springjdbc导入导出excel实例”的主题,详细讲述如何使用这些技术实现数据的导入导出功能。 首先,我们需要了解这些技术的基础概念: 1. POI:Apache POI是一个开源的Java库,用于处理...

    Spring系列面试题129道(附答案解析)

    Spring bean是存储在Spring IoC容器中的Java对象,可以通过容器来配置和管理。 18、spring提供了哪些配置方式? Spring提供了以下配置方式: - 基于XML的配置 - 基于注解的配置 - 基于Java类的配置 19、spring支持...

    基于注解的Spring JdbcTemplate

    Spring JdbcTemplate提供了一个面向对象的接口,用于执行SQL查询、更新和存储过程,避免了直接与JDBC API打交道的繁琐工作。它通过异常处理、事务管理以及结果集的自动处理,简化了数据库访问。基于注解的Spring ...

    java(jdbc)学习

    CallableStatement用于调用数据库的存储过程或函数,支持IN、OUT和IN/OUT参数。 #### 十、元数据信息 JDBC提供了获取数据库和参数元数据的机制,有助于理解数据库结构和优化查询。 #### 十一、批处理的使用 ...

    java JDBC连接数据库代码大全

    ### Java JDBC连接数据库代码大全详解 #### 一、JDBC基础概述 ...随着技术的发展,现代框架如Spring Data JPA等已经极大地简化了这一过程,但在理解更高层次的抽象之前,掌握JDBC的基础是非常重要的。

    spring数据包

    Spring框架以其依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)为核心特性,为开发者提供了大量的模块来处理各种任务,如数据访问、Web开发、事务管理、远程调用等。...

    spring1.2.6源码

    在Spring 1.2.6源码中,我们可以看到以下几个关键知识点: 1. **依赖注入(Dependency Injection,DI)**:这是Spring的核心功能之一,它通过反转控制来管理对象之间的依赖关系。源码中,你可以看到`BeanFactory`...

    Spring 中文开发手册.pdf

    以下是几种常见的整合方式: - **窍门1. 使用Spring的ActionSupport**:Spring 提供了一种机制,可以将Struts的Action对象交给Spring进行管理。这种方式的好处是可以利用Spring的强大功能,如依赖注入、事务管理和...

    spring开发文档

    Spring JDBC提供了一种抽象层,简化了数据库操作,而ORM框架则允许开发者使用面向对象的方式处理数据库交互。 6. **Spring Boot**:Spring Boot是为了简化Spring应用的初始搭建以及开发过程而诞生的。它默认配置了...

    java之JDBC详细介绍

    4. **几种常用数据库的驱动程序及JDBC URL**: 不同数据库的JDBC驱动和URL格式各异,如MySQL的`jdbc:mysql://`,Oracle的`jdbc:oracle:thin:`,SQL Server的`jdbc:sqlserver://`等。 **利用JDBC执行数据库操作** 1....

    JSP与JDBC应用详解

    JDBC包括以下几个核心概念: 1. **Driver Manager**:管理所有已注册的数据库驱动,负责建立数据库连接。 2. **Connection**:代表数据库连接,通过Driver Manager获取。 3. **Statement/PreparedStatement/...

    spring data hadoop reference

    此框架旨在简化在 Hadoop 生态系统中的开发工作,提供了一种更加面向 Spring 的方式来处理 MapReduce 任务、HDFS 文件系统操作以及与 HBase 和 Hive 等数据存储系统的集成。 #### 二、Spring 和 Hadoop ##### 2.1 ...

Global site tag (gtag.js) - Google Analytics