Java调用Oracle存储过程一

2024-09-08 03:32
文章标签 java oracle 过程 调用 存储

本文主要是介绍Java调用Oracle存储过程一,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、通过PL/SQL工具连接上Oracle数据库,创建表zx_test_procedure



二、创建存储过程

①无返回值的存储过程
存储过程为:
create or replace procedure testa
(para1 in varchar2,para2 in varchar2) as
begin
insert into zx_test_procedure(i_id,i_name) values(para1,para2);
end testa;


Java调用的代码:

import java.sql.*;public class TestProcedureOne {public TestProcedureOne() {}public static void main(String[] args ){String driver = "oracle.jdbc.driver.OracleDriver";String strUrl = "jdbc:oracle:thin:@10.10.1.29:1521:testdb";Statement stmt = null;ResultSet rs = null;Connection conn = null;//CallableStatement cstmt = null;try {Class.forName(driver);conn = DriverManager.getConnection(strUrl, "neb", "testneb");CallableStatement proc = null; //创建执行存储过程的对象proc = conn.prepareCall("{call TESTA(?,?) }"); //设置存储过程 call为关键字.proc.setString(1, "400"); //设置第一个输入参数proc.setString(2, "TestFour");//设置第二个输入参数proc.execute();//执行}catch (SQLException ex2) {ex2.printStackTrace();}catch (Exception ex2) {ex2.printStackTrace();}finally{try {if(rs != null){rs.close();if(stmt!=null){stmt.close();}if(conn!=null){conn.close();}}}catch (SQLException ex1) {}}}
}
结果如下:


②有返回值的存储过程(非列表)

存储过程为:

CREATE OR REPLACE PROCEDURE TESTB(PARA1 IN VARCHAR2,PARA2 OUT VARCHAR2) AS
BEGIN 
   SELECT i_name INTO PARA2 FROM zx_test_procedure WHERE I_ID= PARA1; 
END TESTB;


Java调用代码如下:

import java.sql.*;public class TestProcedureTwo {public TestProcedureTwo() {}public static void main(String[] args ){String driver = "oracle.jdbc.driver.OracleDriver";String strUrl = "jdbc:oracle:thin:@10.10.1.29:1521:testdb";Statement stmt = null;ResultSet rs = null;Connection conn = null;//CallableStatement cstmt = null;try {Class.forName(driver);conn = DriverManager.getConnection(strUrl, "neb", "testneb");CallableStatement proc = null; //创建执行存储过程的对象proc = conn.prepareCall("{call TESTB(?,?) }"); //设置存储过程 call为关键字.proc.setString(1, "300"); //设置第一个输入参数proc.registerOutParameter(2, Types.VARCHAR); //第二个参数输出参数,是varchar类型的proc.execute();//执行String test = proc.getString(2);//获得输出参数System.out.println(test);}catch (SQLException ex2) {ex2.printStackTrace();}catch (Exception ex2) {ex2.printStackTrace();}finally{try {if(rs != null){rs.close();if(stmt!=null){stmt.close();}if(conn!=null){conn.close();}}}catch (SQLException ex1) {}}}
}

结果如下:

TestThree

注意,这里的proc.getString(2)中的数值2并非任意的,而是和存储过程中的out列对应的,如果out是在第一个位置,那就是proc.getString(1),如果是第三个位置,就是proc.getString(3),当然也可以同时有多个返回值,那就是再多加几个out参数了。

③返回列表

由于oracle存储过程没有返回值,它的所有返回值都是通过out参数来替代的,列表同样也不例外,但由于是集合,所以不能用一般的参数,必须要用pagkage了.所以要分两部分,
1, 建一个程序包。如下:
create or replace package testpackage as 
type test_cursor is ref cursor;
end testpackage;
2,建立存储过程,存储过程为:
create or replace procedure testc(p_cursor out testpackage.test_cursor) is 
begin 
open p_cursor for select * from zx_test_procedure; 
end testc;
可以看到,它是把游标(可以理解为一个指针),作为一个out 参数来返回值的。

Java调用代码:
import java.sql.*;public class TestProcedureThree {public TestProcedureThree() {}public static void main(String[] args ){String driver = "oracle.jdbc.driver.OracleDriver";String strUrl = "jdbc:oracle:thin:@10.10.1.29:1521:testdb";Statement stmt = null;ResultSet rs = null;Connection conn = null;//CallableStatement cstmt = null;try {Class.forName(driver);conn = DriverManager.getConnection(strUrl, "neb", "testneb");CallableStatement proc = null; //创建执行存储过程的对象proc = conn.prepareCall("{call TESTC(?) }"); //设置存储过程 call为关键字.//设置输出参数是一个游标.第一个参数,游标类型proc.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);proc.execute();rs = (ResultSet) proc.getObject(1);while(rs.next()) {System.out.println(rs.getString(1) + ",,," + rs.getString(2));}}catch (SQLException ex2) {ex2.printStackTrace();}catch (Exception ex2) {ex2.printStackTrace();}finally{try {if(rs != null){rs.close();if(stmt!=null){stmt.close();}if(conn!=null){conn.close();}}}catch (SQLException ex1) {}}}
}
结果如下:
100,,,TestOne
200,,,TestTwo
300,,,TestThree
400,,,TestFour


参考资料:

SELECT INTO STATEMENT
  将select查询的结果存入到变量中,可以同时将多个列存储多个变量中,必须有一条
  记录,否则抛出异常(如果没有记录抛出NO_DATA_FOUND)
  例子:
  BEGIN
  SELECT col1,col2 into 变量1,变量2 FROM typestruct where xxx;
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
      xxxx;
  END;
  ...

关于oracle存储过程的若干问题备忘

1.在oracle中,数据表别名不能加as,如:
select a.appname  from appinfo a; -- 正确
select a.appname  from appinfo  as a; -- 错误
 也许,是怕和oracle中的存储过程中的关键字as冲突的问题吧
2.在存储过程中,select某一字段时,后面必须紧跟into,如果select整个记录,利用游标的话就另当别论了。
   select af.keynode  into kn  from APPFOUNDATION af  where af.appid =aid  and af.foundationid =fid; --  有into,正确编译
   select af.keynode  from APPFOUNDATION af  where af.appid =aid  and af.foundationid =fid; --  没有into,编译报错,提示:Compilation 
  Error: PLS - 00428: an  INTO clause  is expected  in this  SELECT statement

3.在利用select...into...语法时,必须先确保数据库中有该条记录,否则会报出"no data found"异常。
可以在该语法之前,先利用 select count(*) from 查看数据库中是否存在该记录,如果存在,再利用select...into...
4.在存储过程中,别名不能和字段名称相同,否则虽然编译可以通过,但在运行阶段会报错
  select keynode  into kn  from APPFOUNDATION  where appid =aid  and foundationid =fid; --  正确运行
select af.keynode  into kn  from APPFOUNDATION af  where  af.appid = appid  and  af.foundationid = foundationid; --  运行阶段报错,提示
ORA - 01422:exact  fetch  returns more than requested  number  of rows
5.在存储过程中,关于出现null的问题
假设有一个表A,定义如下:
create  table A(
id  varchar2( 50primary  key  not  null,
vcount  number( 8not  null,
bid  varchar2( 50not  null  --  外键 
);
如果在存储过程中,使用如下语句:
select sum(vcount) into fcount from A  where bid='xxxxxx';
如果A表中不存在bid="xxxxxx"的记录,则fcount=null(即使fcount定义时设置了默认值,如:fcount number(8):=0依然无效,fcount还是会变成null),这样以后使用fcount时就可能有问题,所以在这里最好先判断一下:
if fcount  is  null then
    fcount:=0;
end  if;
这样就一切ok了。
6.Hibernate调用oracle存储过程
         this.pnumberManager.getHibernateTemplate().execute(
                 new HibernateCallback()  ... {
                    public Object doInHibernate(Session session)
                            throws HibernateException, SQLException ...{
                        CallableStatement cs = session
                                .connection()
                                .prepareCall("{call modifyapppnumber_remain(?)}");
                        cs.setString(1, foundationid);
                        cs.execute();
                        return null;
                    }

                }
);



这篇关于Java调用Oracle存储过程一的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1146994

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp