java访问oracle存储过程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zjl_csdn/article/details/53946446

存储过程语法见:存储过程语法

在开始做之前,试过用spring管理实现StoredProcedure的类,结果spring初始化必须要有sql,而且在构造函数里面declareParameter,一旦容器管理bean,再想declareParameter,就会报错查询已经编译,不能再declareParameter,所以这里直接用new创建。

建表语句:

create table TESTTABLE
(
  id  VARCHAR2(12),
  name VARCHAR2(32)
);
insert into TESTTABLE (ID, NAME)
values ('1', 'zhangsan');
insert into TESTTABLE (ID, NAME)
values ('2', 'lisi');
insert into TESTTABLE (ID, NAME)
values ('3', 'wangwu');
insert into TESTTABLE (ID, NAME)
values ('4', 'xiaoliu');
insert into TESTTABLE (ID, NAME)
values ('5', 'laowu');


访问代码中主要为以下几个方法,在方法上的注释为oracle proc的代码

toExecute1 StoredProcedure访问一个简单的proc;
toExecute2 同toExecute1,只不过proc稍微复杂一丢丢
toExecute3 StoredProcedure访问一个带游标的proc,返回一个list
testJdbcAccessProc 通过基本的jdbc访问oracle带游标的存储过程。
testJdbcTemplateAccessProc 用spring的JdbcTemplate 访问oracle带游标的存储过程。
 
 





package com.ilovestudy.forum.core.system;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.sql.DataSource;

import oracle.jdbc.OracleTypes;

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.object.StoredProcedure;

public class TestStoredProcedure extends StoredProcedure{
	
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
    	BasicDataSource datasource = context.getBean(BasicDataSource.class);
    	JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
    	TestStoredProcedure test = new TestStoredProcedure(datasource);
    	test.testJdbcTemplateAccessProc(jdbcTemplate);
    	
//    	datasource = test.setDataSourceByFoot();//java中手动配置数据源,同样可用
    	test.toExecute1();
    	test = new TestStoredProcedure(datasource);//每个对象只能编译执行一次,不然再次declare会报错。
    	test.toExecute2();
    	test = new TestStoredProcedure(datasource);
    	test.toExecute3();
    	test = new TestStoredProcedure(datasource);
    	test.testJdbcAccessProc();
	}
	
    public TestStoredProcedure(DataSource dataSource) {
    	super(dataSource,"");//此处暂时设置为空,后面可以再次设置
//    	super();//调用此方法需要设置sql,dataSource/jdbcTemplate
//    	super(jdbcTemplate,procname);//同第一个方法
    }
    
    /**
     * 	测试访问简单的存储过程
	TIPs:
	sql:
		create or replace procedure test_param
			(p_id1 in VARCHAR2 default '0',p_id2 in VARCHAR2,v_name1 out varchar2,v_name2 out varchar2) 
		as
		 -- v_name1 varchar2(2000);--重复定义了
		 -- v_name2 varchar2(2000);--重复定义了
		begin
		  select t.name into v_name1 from TESTTABLE t where t.id = p_id1;
		  select t.name into v_name2 from TESTTABLE t where t.id = p_id2;
		  DBMS_OUTPUT.put_line('name1:' || v_name1||'    name2:'||v_name2);
		end; 
	plsql测试:
		declare v_name1 varchar2(200);
		begin
		test_param('1','3',v_name1,v_name1);
		end;
     */
    
    public Map toExecute1() {
    	String sql = "test_param";
    	setSql(sql);
    	/**declare顺序需要和存储过程参数顺序一致,名字无所谓,*/
    	declareParameter(new SqlParameter("p_id3", Types.VARCHAR));//不过输入参数(p_id3)在paramsIn.put时需要对应
    	declareParameter(new SqlParameter("p_id4", Types.VARCHAR));
    	declareParameter(new SqlOutParameter("name1", Types.VARCHAR));//name1作为返回map的键
    	declareParameter(new SqlOutParameter("name2", Types.VARCHAR));
        Map paramsIn = new HashMap();
        paramsIn.put("p_id3", 1);
        paramsIn.put("p_id4", 3);
        Map rst = super.execute(paramsIn);
        System.out.println("sql:"+sql+"\r\nrst:"+rst);
        return rst ;
    }
    /**
     * 
     * 	稍微复杂点的,不过感觉更多的就是数据库编程了,又没去深入了。
	TIPs:
	sql:
		create or replace procedure test_more
			(p_id1 in VARCHAR2 default '0',p_id2 in number,v_name1 out varchar2,v_name2 out varchar2)
		as
		begin
			
  			select t.name into v_name1 from TESTTABLE t where t.id = p_id1;
  			--在利用select...into...语法时,必须先确保数据库中有该条记录,否则会报出"no data found"异常。
   			--可以在该语法之前,先利用select count(*) from 查看数据库中是否存在该记录,如果存在,再利用select...into...
  			update TESTTABLE set name = 'zhangsan2' where id = 5;
  			select t.name into v_name2 from TESTTABLE t where t.id = p_id2;
  			
    		if (v_name2='wangwu') then
       			select t.name into v_name2 from TESTTABLE t where t.id = p_id2+1;
       			Dbms_output.Put_line('打印信息1:'||v_name2);
    		elsif (v_name2='222') then
       			Dbms_output.Put_line('打印信息2:'||v_name2);
			Else
       			Raise NO_DATA_FOUND;
    		End if;
    		
    		Exception
       			When 
       				others 
    			then
			       v_name2:='3333';
			       Dbms_output.Put_line('打印信息3:'||v_name2);    
			       Rollback;

  			DBMS_OUTPUT.put_line('name1:' || v_name1||'    name2:'||v_name2);
		end;

	plsql测试:
		declare v_name1 varchar2(200);
		begin
		test_more('1','3',v_name1,v_name1);
		end;
     */
    public Map toExecute2() {
    	String sql = "test_more";
    	setSql(sql);
    	/**declare顺序需要和存储过程参数顺序一致,名字无所谓,*/
    	declareParameter(new SqlParameter("p_id3", Types.VARCHAR));//不过输入参数(p_id3)在paramsIn.put时需要对应
    	declareParameter(new SqlParameter("p_id4", Types.VARCHAR));
    	declareParameter(new SqlOutParameter("name1", Types.VARCHAR));//name1作为返回map的键
    	declareParameter(new SqlOutParameter("name2", Types.VARCHAR));
        Map paramsIn = new HashMap();
        paramsIn.put("p_id3", 1);
        paramsIn.put("p_id4", 3);
        Map rst = super.execute(paramsIn);
        System.out.println("sql:"+sql+"\r\nrst:"+rst);
        return rst ;
    }
    
    /**
     * 	测试获取游标
    TIPs  包头和包体需要单独执行
    sql:
	    create or replace package MYPKG as
			type mycursor is ref cursor;
			procedure test(tid in number,mylist out mycursor);
		end MYPKG;
		--分割线--
	    create or replace package body MYPKG as
	    	procedure test(tid in number,mylist out mycursor) as
	        begin
	        	open mylist for select * from testtable where id <= tid;
	        end test;
	    end MYPKG;
	    
	plsql测试:
     * */
    public Map toExecute3() {
    	String sql = "MYPKG.test";
    	setSql(sql);
    	declareParameter(new SqlParameter("id", Types.VARCHAR));
    	declareParameter(new SqlOutParameter("list", OracleTypes.CURSOR,new RowMapper>() {
			@Override
			public Map mapRow(ResultSet rs, int i)
					throws SQLException {
				  	Map map = new HashMap();  
	                map.put("id", rs.getString("ID"));
	                map.put("name", rs.getString("NAME"));  
	                return map;  
			}
		}));
        Map paramsIn = new HashMap();
        paramsIn.put("id", 3);
        Map rst = super.execute(paramsIn);
        System.out.println("sql:"+sql+"\r\nrst:"+rst);
        return rst ;
    }
    
    
    
    /**
     * jdbc	访问存储过程
     */
    public void testJdbcAccessProc(){
    	String[] strs =  getDBdata();
    	String driver 	= strs[0],
		    	url		= strs[1],
		    	acct 	= strs[2],
		    	pwd 	= strs[3];
    	
    	try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
    	Connection conn = null;
		CallableStatement proc = null;
		ResultSet rs = null;
		String sql = "{call MYPKG.test(?,?)}";
    	try {
			conn = DriverManager.getConnection(url, acct, pwd);
			proc = conn.prepareCall(sql);
			proc.setInt(1, 3);
			proc.registerOutParameter(2, OracleTypes.CURSOR);
			proc.execute();
			rs = (ResultSet) proc.getObject(2);//如果不是游标,则直接就可以获取对应的数据!
			while(rs.next()){
				System.out.println("id:"+rs.getString("id")+"\tname:"+rs.getString("name"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally{
			try {
				if(rs!=null){
					rs.close();
				}
				if(proc!=null){
					proc.close();
				}
				if(conn!=null){
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
    }
    /**
     * jdbcTemplate访问proc
     * @param jdbcTemplate
     */
	public void testJdbcTemplateAccessProc(JdbcTemplate jdbcTemplate) {   
        List> resultList = (List>) jdbcTemplate.execute(
        	new CallableStatementCreator() {

				@Override
				public CallableStatement createCallableStatement(Connection con) throws SQLException {   
	                String storedProc = "{call MYPKG.test(?,?)}";// 调用的sql   
	                CallableStatement cs = con.prepareCall(storedProc);   
	                cs.setString(1, "3");// 设置输入参数的值   
	                cs.registerOutParameter(2, OracleTypes.CURSOR);// 注册输出参数的类型   
	                return cs;   
	             }   
        		  
          },new CallableStatementCallback>>(){

				@Override
				public List>  doInCallableStatement(CallableStatement cs)
						throws SQLException, DataAccessException {
					List> list_rst = new ArrayList>();   
			           cs.execute();   
			           ResultSet rs = (ResultSet) cs.getObject(2);// 获取游标一行的值   
			           while (rs.next()) {
			        	  Map rowMap = new HashMap();   
			              rowMap.put("id", rs.getString("id"));   
			              rowMap.put("name", rs.getString("name"));   
			              System.out.println(rowMap);
			              list_rst.add(rowMap);   
			           }   
			           rs.close();   
			           return list_rst;
				}
        	  
          }); 
        
	}
	
	/**手动设置datasource*/
	public BasicDataSource setDataSourceByFoot(){
		String[] strs =  getDBdata();
    	String driver 	= strs[0],
		    	url		= strs[1],
		    	acct 	= strs[2],
		    	pwd 	= strs[3];
    	BasicDataSource ds = new BasicDataSource();      
    	ds.setDriverClassName(driver);      
    	ds.setUrl(url);      
    	ds.setUsername(acct);      
    	ds.setPassword(pwd);  
    	return ds;
	}
	/**获取链接数据库字符串*/
    public String[] getDBdata(){
    	Properties p =new Properties();
    	try {
			p.load(new FileReader("xxxx//db.properties"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
    	String driver 	= p.getProperty("oracle.driver"),
		    	url		= p.getProperty("oracle.url"),
		    	acct 	= p.getProperty("oracle.username"),
		    	pwd 	= p.getProperty("oracle.password");
    	
    	return new String[]{driver,url,acct,pwd};
    }
}



猜你喜欢

转载自blog.csdn.net/zjl_csdn/article/details/53946446