`
windmxf
  • 浏览: 3906 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

JAVA 执行存储过程(和参数顺序无关,适用oracle数据库)

    博客分类:
  • JAVA
阅读更多
通常jdbc调用oracle存储过程的输入输出参数都是按顺序,和java端的参数名称没关系,这样当存储过程修改参数时不是非常方便,字段一旦多的话容易错位,这类问题的排查效率也很低,所以想看看有没有办法java端的key值能和sql的参数名称匹配起来。后来发现pl/sql可以用“参数名=>参数值”的方式调用存储过程。java端的DatabaseMetaData 类也有getProcedureColumns可以得到所有的输入输出参数,这样我的想法就可以通过这两点得以实现。以下就是输入和放回都是map的调用存储过程的方法:
/**
	 * 执行存储过程(和参数顺序无关)
	 * @param procName 存储过程名称
	 * @param procParam 参数(key需大写)
	 * @return
	 */
	public static Map<String, Object> executeProcedure(String procName,
			Map<String, Object> procParam) {
		Connection conn = null;
		CallableStatement cs = null;
		PreparedStatement ps = null;
		ResultSet rs=null;
		String sqlCall = "";
		Map<String, List<Integer>> outParaIdxMap = new LinkedHashMap<String, List<Integer>>();
		try {
			conn = getConnection(dbResourceName);
			DatabaseMetaData dbmd = conn.getMetaData();
			sqlCall = "{call " + procName + "(";
			String pckgName = procName.lastIndexOf(".") > 0 ? procName
					.substring(0, procName.lastIndexOf(".")).toUpperCase()
					: null;//有包体时
			String proc = procName.substring(procName.lastIndexOf(".") + 1,
					procName.length()).toUpperCase();
			rs = dbmd.getProcedureColumns(pckgName,"" , proc, null);
			int i = 1;
			
			while (rs.next()) {// 拼装参数
				String columnName = rs.getString("COLUMN_NAME");
				Short columnType = rs.getShort("COLUMN_TYPE");
				int dataType = rs.getInt("DATA_TYPE");
				List<Integer> outParaList=new ArrayList<Integer>();
				if (DatabaseMetaData.procedureColumnIn==columnType){
					sqlCall += columnName + "=>'" + procParam.get(columnName)
					+ "',";
				}
				else if (DatabaseMetaData.procedureColumnOut==columnType) {// 输出参数
					sqlCall += columnName + "=>?,";
					outParaList.add(i);
					outParaList.add(dataType);
					outParaIdxMap.put(columnName,outParaList);
					
					i++;
				}
				
			}
			sqlCall = sqlCall.substring(0, sqlCall.lastIndexOf(",")) + ")}";//去除参数最后一个逗号以及后面的部分
			cs = conn.prepareCall(sqlCall);
			for (String key : outParaIdxMap.keySet()) {
				int idx=outParaIdxMap.get(key).get(0);//顺序
				int dataType=outParaIdxMap.get(key).get(1);//dataType
				cs.registerOutParameter(idx, dataType);
			}
			cs.execute();
			for (String key : outParaIdxMap.keySet()) {//组装输出参数值(保留输入参数值)
				int idx=outParaIdxMap.get(key).get(0);//顺序
				procParam.put(key, cs.getObject(idx));
			}
			conn.commit();
		

		} catch (Exception e) {
			System.err.println("SQLException proc=[" + sqlCall + "] ");
			try {
				if (conn != null)
					conn.rollback();
			} catch (SQLException sqlex) {
				sqlex.printStackTrace();
			}
			e.printStackTrace();

		} finally {
			closeRsPsConn(rs, ps, conn);
			closeCsPsConn(cs, ps, conn);
		}
		return procParam;
	}
/**
	 * 把key装换为大写便于后台处理
	 * @param map
	 * @return
	 */
    public static Map<String, Object> convertUpperCaseMap(Map<String, ?> map) {
		Map<String, Object> returnMap=new LinkedHashMap<String, Object>();
		for (String key : map.keySet()) {
			returnMap.put(key.toUpperCase(), map.get(key));
		}
		return returnMap;
	}

开发中遇到的问题:
1.本来CallableStatement 是提供setString(ParameterName,value)这样的方法的,但是看了ibm网站上的资料发现不支持oracle,是infomix的特性,所以无法用,只能麻烦点用index的方式注册输出参数
2.另外所有的参数包括存储过程名称、包名都要大写,否则不认得
3.使用getProcedureColumns(pckgName,"" , proc, null);时注意 第一个参数catalog对应oracle的包名,第二个参数应该是schema名称,我一开始以为是用户名,但不对,只能写空,但不要写null,否则会得到这个实例里面所有这个存储过程的参数,当实例存在多个用户的使用会有问题。
分享到:
评论
1 楼 kongfwy 2013-08-13  
这个没考虑到in out类型的参数,如果调用的存储过程里有这类参数(即是in又是out)就会出错,参考你这个思路我写了一个类似的,可以避免以上问题。链接地址:http://kongfwy.iteye.com/blog/1924077

相关推荐

    Java链接Oracle 存储过程 jdbc BLOG

    在Java编程中,连接Oracle数据库并执行存储过程是常见的任务,尤其在企业级应用中,存储过程被广泛用于实现复杂的业务逻辑和优化数据操作。本文将深入探讨如何使用JDBC(Java Database Connectivity)API来调用...

    java调用oracle存储过程或者函数

    在Java编程中,调用Oracle数据库的存储过程和函数是常见的任务,这通常涉及到JDBC(Java Database Connectivity)API的使用。以下将详细介绍这个过程,包括必要的步骤、使用的类和方法,以及可能遇到的问题和解决...

    Oracle数据库存储过程.pdf

    存储过程和触发器是Oracle数据库中重要的组件,它们是用于封装一系列操作的数据库对象。 首先,存储过程是一组为了完成特定功能的SQL语句集,它可以接受参数、执行复杂的逻辑,并可以返回结果。存储过程的执行速度...

    java调用Oracle存储过程

    在Java编程中,调用Oracle数据库的存储过程是常见的任务,尤其在处理复杂业务逻辑或数据操作时。本文将深入探讨如何使用Java与Oracle数据库进行交互,并调用存储过程。 首先,确保你已经在你的开发环境中安装了...

    java 调存储过程

    例如,如果存储过程有一个输入参数和一个输出参数: ```java cs.setInt(1, inputValue); // 输入参数 cs.registerOutParameter(2, Types.INTEGER); // 输出参数,Types.INTEGER是Java.sql.Types中的常量 ``` 3....

    Java调用Oracle存储过程的方法

    在Java编程中,调用Oracle数据库的存储过程是常见的任务,尤其在处理复杂业务逻辑或数据操作时。本文将详细讲解如何使用Java调用Oracle存储过程,并提供示例代码。 首先,我们需要了解Java中用于与数据库交互的核心...

    jeecms的oracle数据库脚本及初始化数据

    Oracle数据库脚本通常用于创建数据库结构,包括表、视图、存储过程、函数等,以及填充初始数据。在Jeecms的上下文中,`oracle_jeecms-initdata.sql`和`oracle10g-jeecms-table.sql`两个文件分别承担了不同的任务。 ...

    java调用存储过程

    Java调用存储过程是数据库操作中的常见任务,特别是在Oracle数据库中。存储过程是预编译的SQL语句集合,可以在数据库服务器端执行,提高性能并减少网络数据传输。本篇文章将详细讲解如何在Java应用程序中调用Oracle...

    用JDBC操作Oracle的存储过程返回值

    总的来说,使用JDBC操作Oracle的存储过程返回值涉及了JDBC的基本操作,包括加载驱动、建立连接、创建CallableStatement、设置参数、执行存储过程、获取返回值以及释放资源。理解这些步骤对于开发与Oracle数据库交互...

    java连接Oracle数据库简单示例

    2. **Oracle JDBC Driver**: Oracle提供了适用于Java的JDBC驱动程序,使得Java应用能够连接到Oracle数据库。在这个示例中,我们使用的是`oracle.jdbc.driver.OracleDriver`,这是Oracle JDBC Thin驱动,它是一个纯...

    Oracle集合类型输出参数的PLSQL存储过程及其Java调用.docx

    在这个Java程序中,我们首先连接到Oracle数据库,然后使用`OracleCallableStatement`调用存储过程。通过`registerOutParameter`注册输出参数,这里使用了游标类型,因为索引表不能直接通过标准SQL语句返回。接着,...

    oracle数据库文本文档

    2. **索引组织表**:数据按索引顺序存储,适用于频繁使用索引查找的情况。 3. **数据压缩**:通过压缩技术减少存储空间的需求,同时保持较高的数据读取速度。 4. **实时应用集群**:提供高可用性和负载均衡功能,...

    如何使用Oracle数据库实现实时通信

    在Oracle数据库开发中,实时通信是一项重要的需求,尤其是在调试存储过程和进行远程监控时。传统的DBMS_OUTPUT.PUT_LINE方法虽然方便,但其信息反馈存在延迟,直到整个过程执行完毕才会显示输出。为了解决这个问题,...

    Java调用存储过程.doc

    3. 执行存储过程:调用CallableStatement的execute()方法执行存储过程。 4. 处理结果:如果存储过程有返回值,可以通过CallableStatement获取。如果没有返回值,执行成功与否通常通过异常捕获来判断。 存储过程的...

    java存储oracle中的clob类型

    在Java编程中,为了能够有效地与Oracle数据库中的CLOB类型交互,Java提供了`java.sql.Clob`类作为接口。 **1. CLOB的读取方法** - **getCharacterStream()**:返回一个`java.io.Reader`对象,按照Unicode编码读取...

    JDBC实用技术(连接Oracle数据库)

    **JDBC实用技术——连接Oracle数据库** ...总结来说,JDBC连接Oracle数据库涉及驱动的配置、连接的创建和管理以及SQL语句的执行。通过熟练掌握这些技能,开发者可以有效地在Java应用程序中与Oracle数据库进行交互。

    Oracle数据库试题100题(附答案)

    - **答案解析**: 在Oracle数据库服务器启动过程中,需要读取几种关键文件来确保系统的正常运行。其中数据文件(Data Files)、控制文件(Control Files)和重做日志文件(Redo Log Files)是必不可少的。而**归档日志文件...

    ORACLE数据库管理基础2.pptx

    Oracle数据库管理基础是数据库管理员(DBA)必备的知识领域,本课主要涵盖了Oracle数据库的一些核心管理工具和技术。首先,我们来详细了解一下Oracle Universal Installer (OUI)、SQL*Plus、Oracle Enterprise ...

    java中调用oracle

    本篇将详细阐述如何在Java中与Oracle数据库进行交互,尤其是涉及存储过程的调用。 首先,我们需要在Java项目中引入Oracle的JDBC驱动。Oracle提供了一个名为ojdbc的驱动库,如`ojdbc8.jar`或`ojdbc14.jar`等,根据...

Global site tag (gtag.js) - Google Analytics