oracle存储过程及Java调用(转)
来源:互联网 发布:mac android ant 编辑:程序博客网 时间:2024/05/21 07:46
初次研究出bug的地方非常多,所以注意点非常多,花了我三天时间除尽所有bug,我会把注意点都列出来,可能有落下的地方,还请多指正,相互探讨。
首先上最终测试成功版存储过程代码:(里面代码可能不尽对你都有用,借鉴参考吧,我全贴出来也是为了我以后好查)
说一下jar包用的是ojdbc14.jar,至于什么class12.jar、ojdbc6.jar啊应该都可以,只要一种就可以了。
说说我的需求,以便让大家更顺利的看懂我的代码,我的需求是:存储过程从Java端接收两个参数userid(用户)和topicid(话题),在存储过程进行循环查询当前用户对当前话题的点赞记录,如果有记录,则record为设置1,没有则为0,最后返回一个结果集,是反应 用户=>话题=>record相互对应的关系表。
好了不废话了,上代码吧,学习阶段,所以难免情绪波动和啰嗦,也是希望以最直白能懂的方式叙述出来。
-
- create or replace type tp_arr3 as Object
- (
- userid nvarchar2(40),
- topicid nvarchar2(40),
- record nvarchar2(4)
- )
-
-
- CREATE OR REPLACE TYPE tp_arr_tbl3 AS TABLE OF tp_arr3
-
- create or replace package testpkg as
- type testcur is ref cursor;
- end testpkg;
-
- CREATE OR REPLACE procedure findRecord(type_obj IN tp_arr_tbl3,result out testpkg.testcur)
- as
- t tp_arr3;
- sql2 varchar2(500);
- sql3 varchar2(500);
- v_count varchar2(4);
- BEGIN
- sql2 :='drop table tb_temp';
- sql3 :='CREATE TABLE tb_temp( userid varchar2(40),topicid varchar2(40) primary key, record varchar2(4))';
- execute immediate sql2;
- execute immediate sql3;
-
- FOR i IN type_obj.first()..type_obj.last()
- LOOP
- t:= type_obj(i);
- select count(*) into v_count from scott.tb_praise_rel where userid=t.userid and topicid=t.topicid;
- dbms_output.put_line( t.userid || '=>'||t.topicid ||'=>' || v_count);
- insert into tb_temp values (t.userid,t.topicid, v_count);
- END LOOP;
- COMMIT;
-
- open result for select * from tb_temp;
- END;
-
-
- declare
- ta tp_arr_tbl3:=tp_arr_tbl3();
- t tp_arr3:=tp_arr3('0','0','0');
- begin
- for i in 1..12 loop
- ta.extend;
- t.userid:='1';
- t.topicid:=i;
- t.record:='0';
- ta(i):=t;
- findRecord(ta);
- end loop;
- end findRecord;
-
-
- select * from tb_temp;
-
- select * from scott.tb_praise_rel;
-
- select userid from scott.tb_praise_rel where userid='1' and topicid='1';
-
- cursor testcur is select userid,topicid from scott.tb_praise_rel;
- cur testcur%rowtype;
-
- open testcur;
- loop
- fetch testcur into cur;
- exit when testcur%notfound;
- dbms_output.put_line( 'userid:' || cur.userid || ',topicid:' || cur.topicid );
- update tb_temp set record='1' where userid=cur.userid and topicid=cur.topicid;
- end loop;
- dbms_output.put_line('----------------------');
- close testcur;
- COMMIT;
注意点:1.测试用户起初用的Scott,发现没有执行权限,对其进行赋予dba权限还是不行,遂后来用的system;2.多次测试创建可能会出现“ORA-02303: 无法使用类型或表的相关性来删除或取代一个类型”这个错误,这时只要换一个类型名字再创建就可以了;3.由于我的tb_temp表有唯一字段约束,所以存储过程每次进来先删表,再建表,再插入数据;4.记得该打分号的地方不要漏,不该打的地方不要多;5.执行存储过程的时候,要先声明并赋初值,不然也会报错;6.注意pl/sql里执行存储过程测试赋值时候ta.extend不能少;6.自定义类型要注意的地方很多,比如nvarchar2和JavaString类型的定义;7.简单说tp_arr3 类型是指一条记录,tp_arr_tbl3是指多条记录;
-
- create table tb_praise_rel(
- id varchar2(40) primary key,
- userid varchar2(40),
- topicid varchar2(40),
- remarks1 varchar2(3000),
- remarks2 varchar2(3000),
- remarks3 varchar2(3000)
- );
再上Java调用代码:
- package com.lofter.svntesr;
-
- import java.sql.Array;
- import java.sql.CallableStatement;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Map;
-
- import oracle.jdbc.OracleTypes;
- import oracle.sql.STRUCT;
- import oracle.sql.StructDescriptor;
-
- import com.lofter.bean.ProcedureBean;
-
- public class ProcedureTest3 {
-
-
-
-
- public static void main(String[] args) {
- try {
-
- Class.forName("oracle.jdbc.driver.OracleDriver");
-
- String url = "jdbc:oracle:thin:@localhost:1521:orcl";
-
-
- Connection con = DriverManager.getConnection(url, "system", "a");
-
-
- CallableStatement cs = null;
- ResultSet rs=null;
-
- List<ProcedureBean> list = new ArrayList<ProcedureBean>();
- for (int i = 1; i <= 12; i++) {
- String r = i + "";
- list.add(new ProcedureBean("1", r, "0"));
- }
-
-
-
-
- StructDescriptor recDesc = StructDescriptor.createDescriptor(
- "TP_ARR3", con);
-
-
- ArrayList<STRUCT> pstruct = new ArrayList<STRUCT>();
- for (ProcedureBean pb : list) {
- System.out.println(pb);
- Object[] objs = new Object[3];
- objs[0] = pb.getUserid();
- objs[1] = pb.getTopicid();
- objs[2] = pb.getRecord();
- STRUCT item = new STRUCT(recDesc, con, objs);
- pstruct.add(item);
- }
-
-
- oracle.sql.ArrayDescriptor desc = oracle.sql.ArrayDescriptor.createDescriptor("TP_ARR_TBL3", con);
-
- oracle.sql.ARRAY array = new oracle.sql.ARRAY(desc, con, pstruct.toArray());
-
-
- cs = con.prepareCall("{call findRecord(?,?)}");
-
-
- cs.setArray(1, array);
- cs.registerOutParameter(2, OracleTypes.CURSOR);
- cs.execute();
- rs=(ResultSet) cs.getObject(2);
-
- while( rs.next() ){
- System.out.println("result : \t" + rs.getString(1)+"\t"+rs.getString(2)+"\t"+rs.getString(3));
- }
- con.commit();
- } catch (Exception e) {
-
- e.printStackTrace();
-
- }
-
- }
- }
Java调用注意:基本上注意事项都以注释的方式写在代码里了,也有可能没想起来,很多bug信息由于测试通过心切,没能及时复制下来。注意不要导错包2.错误信息“Message file 'oracle.jdbc.driver.Messages' is missing.”,可能是你写错了或类型与oracle中不匹配,不要去找什么jar包啊什么的,网上信息也不多,我在这绕了好久,多检查一下上面提到的加包名、大小写、转类型什么的;
还有其他没想起来或没碰到的bug只有亲们多结合错误信息猜测,多动手测测,相信就会迎刃而解了。
测试的javaBean:
- package com.lofter.bean;
-
- import java.io.Serializable;
-
- public class ProcedureBean implements Serializable {
-
- private static final long serialVersionUID = 809894604693791308L;
- private String userid;
- private String topicid;
- private String record;
-
- public ProcedureBean() {
- super();
- }
-
- public ProcedureBean(String userid, String topicid, String record) {
- super();
- this.userid = userid;
- this.topicid = topicid;
- this.record = record;
- }
-
- public String getUserid() {
- return userid;
- }
-
- public void setUserid(String userid) {
- this.userid = userid;
- }
-
- public String getTopicid() {
- return topicid;
- }
-
- public void setTopicid(String topicid) {
- this.topicid = topicid;
- }
-
- public String getRecord() {
- return record;
- }
-
- public void setRecord(String record) {
- this.record = record;
- }
-
- @Override
- public String toString() {
- return "ProcedureBean [userid=" + userid + ", topicid=" + topicid
- + ", record=" + record + "]";
- }
-
- }
0 0