java调用带有自定义类型参数的存储过程
java调用带有自定义类型参数的存储过程
华航小辉 发表于2年前
java调用带有自定义类型参数的存储过程
  • 发表于 2年前
  • 阅读 61
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云实验室 1小时搭建人工智能应用,让技术更容易入门 免费体验 >>>   

摘要: 整体思路可以分为存储过程和java调用程序两个方面。存储过程层面:在数据库中建立了两个type:array 和 list ,在存储过程中遍历list取出array,然后给存储过程中的四个变量赋值,进行一些插入操作等。java调用程序方面:接受参数封装到bean中,然后add到list中,然后将java类型的list转变成oracle中自定义类型的包含array的list。最后java调用程序和oracle存储过程对接完毕之后,批量插入数据。

        最近工作中遇到了这样的一个需求,需要我批量的导入一下数据,但是公司的框架对事务的支持不是很好,所以考虑了之后希望把事务放到数据库中实现,于是就想到了写一个带有数组参数的存储过程,于是在网上找了好多资料,经过自己试验之后,完成了这篇博文,也是我的第一篇博文。在这里插一句题外话:“只要你想去做,努力的去做,我们就可以实现我们的需求!”

        首先、建立一张表userinfo,userid就是身份证号

create table userinfo(
    userid varchar2(20) primary key,
    uname varchar2(20) not null,
    usex number(1) not null,
    uaddr varchar2(100) not null);

       然后、需要在数据库中创建两个type,用来对数据进行封装

        创建的是一个array类型,用来封装java中的一个对象数据

create or replace type array_user as object
(    userid nvarchar2(20),
     uname nvarchar2(20),
     usex number(1),
     uaddr nvarchar2(100)
);

        再创建一个list类型,用来封装多个java对象信息,当list的长度大于5000的时候,就会分批次传递参数执行proc

create or replace tepe list_user as varray(5000) of array_user;

      接下来就是一个重头戏了,存储过程

create or replace procedure proc_user(
        i_array in list_user,
        o_errcode out number,
        o_errdesc out varchar2) is
 v_userid nvarchar2(20);
 v_uname nvarchar2(20);
 v_usex nvarchar2(1);
 v_uaddr nvarchar2(100);
 v_type array_user;
 begin
     for i in 1..i_array.count loop
        v_type:=i_array(i);
        v_userid:=v_type.userid;
        v_uname:=v_type.uname;
        v_usex:=v_type.usex;
        v_uaddr:=v_type.uaddr;
     insert into userinfo 
     values(v_userid,v_uname,v_usex,v_uaddr);
     end loop;
     commit;
     o_errcode:=0;
     o_errdesc:='成功返回';
     Exception
         when Dup_val_on_index then 
             o_errcode:=1;
             o_errdesc:='违反唯一性约束';
         when others then 
             o_errcode:=SQLCODE;
             o_errdesc:=SUBSTR(SQLERRM,1,200);
         rollback;
   end proc_user;

        存储过程写完了,剩下的就是java代码了,调用带自定义类型的存储过程

package elmp_test;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import oracle.jdbc.OracleCallableStatement;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;
import oracle.sql.STRUCT;
import oracle.sql.StructDescriptor;
    @SuppressWarnings("unchecked")  
    public class TestProc {  
      
        public static void main(String[] args) { 
        	String downloadpath = "http://www.test.com";
            List arrayL = new ArrayList();
            User u = new User();
            u.setUserid("333");
            u.setUname("xiaohua");
            u.setUsex(1);
            u.setUaddr("北京市海淀区");
            arrayL.add(u);
            User u1 = new User();
            u1.setUserid("444");
            u1.setUname("xiaohui");
            u1.setUsex(0);
            u1.setUaddr("北京市昌平区");
            arrayL.add(u1);    
            
            try {  
                /* 
                 * 记得判断一下list集合的大小、如果集合大于你在数据设置的数组大小了、那么就要分批次提交 
                 * 我的是y_Oracle_LIST AS VARRAY(5000)  
                 * 那么当list集合的值等于5000的时候就入库了、 
                 * 然后剩下的数据又从新用一个list来装、在继续判断...... 
                 * 这里只是简单的演示、就不具体操作判断了 
                 */  
                int backVal = newTest(arrayL);  
                System.out.println(backVal==0?"成功!":"失败!");  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
        /** 
         * 将java中的arrayList转化 
         * @param con 数据库连接对象 
         * @param Oraclelist 数据数组类型名称 
         * @param objlist 要存储的list对象 
         * @return oracle.sql.ARRAY 
         * @throws Exception 
         */  
        private static ARRAY getOracleArray(Connection con, String Oraclelist,  
                List objlist) throws Exception {  
            ARRAY list = null;  
            if (objlist != null && objlist.size() > 0) {  
                /** 
                 * 必须大写类型名称 
                 * 否则会报错:java.sql.SQLException: 无效的名称模式: M_ORDER.yoracleobject 
                 */  
                StructDescriptor structdesc = new StructDescriptor(  
                        "ARRAY_USER", con);   
                STRUCT[] structs = new STRUCT[objlist.size()];  
                Object[] result = null;  
                for (int i = 0; i < objlist.size(); i++) {  
                    result = new Object[4];   
                    User t = (User)(objlist.get(i));  
                    result[0] = t.getUserid();  
                    result[1] = t.getUname();  
                    result[2] = t.getUsex();
                    result[3] = t.getUaddr();;  
                    /* 
                     * 一定要记得导入orai18n.jar 
                     * 否则一遇到字符串就乱码、添加不到数据 
                     */  
                    structs[i] = new STRUCT(structdesc, con, result);  
                }  
                ArrayDescriptor desc = ArrayDescriptor.createDescriptor(Oraclelist,  
                        con);  
                list = new ARRAY(desc, con, structs); 
                
            } else {  
                ArrayDescriptor desc = ArrayDescriptor.createDescriptor(Oraclelist,  
                        con);  
                STRUCT[] structs = new STRUCT[0];  
                list = new ARRAY(desc, con, structs);  
            }  
            return list;  
        }   
          
        /** 
         * 入库 
         * @param peoleList 要存储的list对象 
         * @return 
         * @throws SQLException 
         */  
        public static int newTest(List peoleList) throws SQLException{  
            Connection con = null;  
            CallableStatement stmt = null;  
            int backVal = -1; 
            String message = null;
            try {  
                DbUtil d = new DbUtil();  
                con = d.getCon();  
                if (con != null) {  
                    stmt = con.prepareCall("{call proc_user(?,?,?)}");  
                    ARRAY adArray = getOracleArray(con, "LIST_USER",peoleList);  
                    ((OracleCallableStatement) stmt).setARRAY(1, adArray);  
                    stmt.registerOutParameter(2, java.sql.Types.INTEGER);
                    stmt.registerOutParameter(3, java.sql.Types.LONGNVARCHAR);
                    stmt.execute();   
                    backVal = stmt.getInt(2);
                    message = stmt.getString(3);
                }  
            } catch (Exception e) {  
                e.printStackTrace();   
            } finally {  
                if(stmt!=null){  
                    stmt.close();  
                }  
                if(con!=null){  
                    con.close();  
                }  
            }  
            return backVal;  
        }  
    }

        DButils工具类

package elmp_test;

import java.io.IOException;  
import java.io.InputStream;  
import java.sql.Connection;  
import java.sql.DriverManager;  
import java.util.Properties; 
import oracle.jdbc.driver.*;

  
@SuppressWarnings("unused")
public class DbUtil {  
    static Properties properties = null;  
  
    public DbUtil() {  
        // 读取.properties文件的信息  
        properties = new Properties();  
        InputStream in = getClass().getResourceAsStream("/elmp/test/oracleproceduretest/ordermanager.properties");  
        try {  
            properties.load(in);    
        } catch (IOException ex) {  
            System.out.println(ex.getMessage());  
            ex.printStackTrace();  
        }  
    }  
      
    /** 
     * <LI>获取连接对象</LI> 
     *  
     * @return 
     */  
     public Connection getCon() {  
            Connection connection = null;    
            try {  
                String url=properties.getProperty("jdbc.url");  
                String user=properties.getProperty("jdbc.username");  
                String pwd=properties.getProperty("jdbc.password");  
                String driver=properties.getProperty("jdbc.driverClassName");  
                Class.forName(driver);                   
                connection = DriverManager.getConnection(url, user, pwd);  
            } catch (Exception err) {  
                System.out.println("错误:ConDB-->getCon()____JDBC连接失败!");  
                err.printStackTrace();  
                return null;  
            }  
            return connection;  
    }    
}

        properites

    

jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@//192.168.225.132:1521/orcl
jdbc.username=hc
jdbc.password=hctest

    最后说明:

            之前在网上查到的相应的代码,在执行的时候老师出错,原因是java程序调用存储过程时,参数没有赋上值,导致无法插入null值,原因是因为array_user中的字段类型,如果有varchar2类型的,请改成nvarchar2类型,这样就可以神奇的赋值了,没有错误的感觉就是爽啊!

            要有一颗发现问题,解决问题的心,这样我们才可以在技术的道路上,走的更远,更远!

共有 人打赏支持
粉丝 2
博文 1
码字总数 1344
×
华航小辉
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: