存储过程语法见:存储过程语法,
在开始做之前,试过用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,返回一个listtestJdbcAccessProc 通过基本的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