1.在plsql中,自定义一对象,包含 某些值;
CREATE OR REPLACE TYPE obj008  AS OBJECT
(
policy_no  VARCHAR2(20),
check_date DATE,
check_ VARCHAR2(01),
check_opt  VARCHAR2(01),
check_ind  VARCHAR2(01),
CONSTRUCTOR FUNCTION obj008 RETURN SELF AS RESULT
)2.再定义一数组,数组元素为自定义对象obj
CREATE OR REPLACE TYPE nt_rec_objs  IS TABLE OF obj008 3.然后查询一些数据插入,形成一个对象数组。
java中怎么获取这个对象数组,并逐字段读 出来了??

解决方案 »

  1.   

    粗略的写了以下实现方法,代码很不规范。Orlace侧的代码。
    类型定义:
    -------------------------------------------------------
    CREATE OR REPLACE TYPE C20.OBJ008  AS OBJECT 

    A  VARCHAR2(20), 
    B DATE,
    C VARCHAR2(01), 
    D  VARCHAR2(01), 
    E VARCHAR2(01), 
    CONSTRUCTOR FUNCTION OBJ008 RETURN SELF AS RESULT 
    ) CREATE OR REPLACE TYPE C20.T_OBJ IS TABLE OF OBJ008;
    --------------------------------------------------------
    函数定义:
    --------------------------------------------------------
    CREATE OR REPLACE FUNCTION C20.DPJAVA(val NUMBER) RETURN T_OBJ
    IS
    I NUMBER;
    OBJ OBJ008;
    TJ T_OBJ;
    BEGIN
      I := 0;
      TJ := T_OBJ();--対象初期化
      LOOP
        EXIT WHEN I > val;
        I := I + 1;
        OBJ := OBJ008();  --対象初期化
        OBJ.A := TRIM(TO_CHAR(I,'000000000'));
        TJ.EXTEND;--対象増数
        TJ(I) := OBJ;
      END LOOP;
      RETURN TJ;
    END;
    --------------------------------------------------------
    java端的代码片段。
    --------------------------------------------------------
    conn = getConnection();
    String sql="{? = call DPJAVA(?) }";
    OracleCallableStatement stmt = (OracleCallableStatement) conn.prepareCall(sql);
    stmt.setInt(2,10);
    stmt.registerOutParameter(1,OracleTypes.ARRAY,"T_OBJ");
    stmt.execute();
    ARRAY simpleArray = stmt.getARRAY(1);
    Object[] ay = (Object[])simpleArray.getArray();
    int i = ay.length;
    STRUCT st = (STRUCT)ay[1];
    Object[] ay = (Object[])simpleArray.getArray();
    int i = ay.length; //取得行数
    STRUCT st = (STRUCT)ay[0];//取第0行记录
    Object[] oj = st.getAttributes();
    String str = (String)oj[0];//字段A的值
    System.out.println(str);
    stmt.close();
    conn.close();
    ----------------------------------------------------
      

  2.   

    楼上的代码运行过吗?
    如果在thin连接方式下,
    我估计会在stmt.execute()这一行抛出异常原因在于java代码在thin连接方式下没有合适的对象接收table类型,即这一句
    stmt.registerOutParameter(1,OracleTypes.ARRAY,"T_OBJ")中使用的OracleTypes.ARRAY类型不能正常接收存储过程的table
    java中的Array对象我也试过,一样不能正常接收
    当时我甚至想过重写驱动包,但是这个方案由于复杂和稳定性的考虑被否定了这个问题我作过浅短探究,
    结论是在服务器端的话使用oci的连接方式是可行的,
    调用时记得使用OracleCallableStatement对象而非CallableStatement就可thin方式下我的方法是创建临时表(临时表往往没有我们想象的那样麻烦),
    然后使用游标返回结果,而不是table类型当时我也搜索了好多网页,浪费了很多时间
    但愿楼主少走弯路,能早日找到可行的解决办法
      

  3.   

    楼上的大哥,如果没有运行过怎么可能贴上来呢?
    我只是不想把我是沿用的代码完整的Copy过来而已。
    那么我把代码贴完整,包括环境。(我指的是Java部分,PLSQL我已经贴的很完整了)
    Oracle 10g JDK 1.5
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.Map;import oracle.jdbc.OracleCallableStatement;
    import oracle.jdbc.OracleTypes;
    import oracle.jdbc.oracore.OracleType;
    import oracle.sql.*;
    public class plsql {
    public  static Connection getConnection() throws Exception {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            return DriverManager.getConnection(
                    "jdbc:oracle:thin:@127.0.0.1:1521:Doer", "Doer", "Doer");
        } 
    public static void main(String[] args) throws Exception{
    Connection conn = null;
    try{
    conn = getConnection();
    String sql="{? = call DPJAVA(?) }";
    OracleCallableStatement stmt = (OracleCallableStatement)conn.prepareCall(sql);
    stmt.setInt(2,10);
    stmt.registerOutParameter(1,OracleTypes.ARRAY,"T_OBJ");
    stmt.execute();
    ARRAY simpleArray = stmt.getARRAY(1);
    //     System.out.println("Array is of type " +  simpleArray.getSQLTypeName());
    //     System.out.println("Array element is of type code "+simpleArray.getBaseType());
    //     System.out.println("Array is of length " + simpleArray.length());
        Object[] ay = (Object[])simpleArray.getArray();
        int i = ay.length;
        STRUCT st = (STRUCT)ay[0];
    System.out.println("++++"+st.getSQLTypeName());
    Object[] oj = st.getAttributes();
    String str = (String)oj[0];
    System.out.println(str);
            stmt.close();
            conn.close(); }catch(Exception e){
    e.printStackTrace();
    conn.close();
    }
    }}
      

  4.   

    以上使用的就是thin方式连接数据库,没有人说过Oracle不支持从PLSQL中返回Table或者可变数组。
    其实很多时候去google或者baidu需要的只是倒不如看看Oracle提供的官方文档。
    建议看看Oracle官方提供的JDBC的资料,其中专没有oracle对象(Object)、可变数组等在JDBC中如何使用的介绍。
    当然,本人也是第一次尝试如此调用,解决方法可能会有与本地环境高度聚合的情况。
    愿意与大家探讨!
      

  5.   

    我试了一下,在这一行
    stmt.registerOutParameter(1,OracleTypes.ARRAY,"T_OBJ");

    Exception in thread "main" java.sql.SQLException: 无效的名称模式:Doer.T_OBJ
    运行的时候我加了我本地Scheme的前缀,当然不是Doer,所以我也报的错相应地改了下我觉得,
    应该是java不认类型T_OBJ,
    楼上能指点一下吗?我很想搞清这个问题有点怀疑是我的ojdbc14.jar了不知道楼主解决了没
      

  6.   

    楼上,如果在我本地把代码改成
    stmt.registerOutParameter(1,OracleTypes.ARRAY,"T_OBJ_XXX");
    也会报出拟以行的错误,原因是"T_OBJ_XXX"不是我数据库内存在的TYPE。
    执行java之前,一定要在DB中建立这个类型,
    CREATE OR REPLACE TYPE Doer.T_OBJ IS TABLE OF OBJ008;
    并且保证OBJ008和T_OBJ都是有效的。
      

  7.   

    这个我已经做了,不然的话存储过程也通不过啊问题是java代码找不到它
      

  8.   

    我单独执行存储过程是成功的,
    也能修改数据库和打印结果,
    虽然我的存储过程和你的不一样,
    但是意思是一样的,就是调用返回table这个自定义的table类型无论我把它定义在包里面不是包外面java都不认,我都服了
      

  9.   

    真晕,前面就报错了
        ResultSet rs = null;
        List tGroups = null;
        DBean db = new DBean();
        List destList = null;
        TCustomerBirthday destObj = null;
        try {
            //Session s = HibernateSession.currentSession();
            db.connect();
            Connection con = db.getConnection();
            cstmt = (OracleCallableStatement)con.prepareCall("{call PKG_QRY_CS.p_gen_cust_birt(?,?,?,?,?)}");
            cstmt.setLong(1, search.getMonth().longValue());
            cstmt.setString(2, search.getAgentCode());
            cstmt.setString(3, search.getAgencyOffice());
            cstmt.setString(4, search.getRegionCode());
            cstmt.registerOutParameter(5, OracleTypes.ARRAY,"o_t_cust");
            cstmt.execute();
            //Get result
            Array arr = cstmt.getArray(1);
            if(arr != null){
              Object[] arrList = (Object[])arr.getArray();
              destList = new ArrayList();
              for(int i = 0;i < arrList.length;i++){
                STRUCT struct = (STRUCT)arrList[i];
                Datum[] dt = struct.getOracleAttributes();
                destObj = new TCustomerBirthday();
                for(int j=0;j<dt.length;j++){
                  //destObj.setCustomerNo(new Long(dt[j].toString()));
                  //destObj.setCustomerName(dt[])
                  System.out.println(dt[j]);
                }
              }
            }        return tGroups;
        } catch (Exception e) {
          e.printStackTrace();
          Logs.info(TCustomerBirthdayDelegate.class, e);
          throw ExceptionFactory.parse(e);
        } finally {
          DBean.closeAll(rs, cstmt, db);
        }
    红色部分报错:
     java.lang.ClassCastException环境:
    JDK1.4
    Tomcat5.0
    Oracle10g
      

  10.   

    找到了上面的错误,
    数据库通过JNDI连接,就会报出ClassCastException异常,如果直接用JDBC连接就不会抛出这个异常,原因虽然找到仍不知道如何用JNDI才能通过,大家继续讨论呵?这个错误解决后,又报错,与lpc19598188 相同错误,
    抛出:无效的名称模式,
    单独执行存储过程也是可以的。
    不知lpc19598188 解决了没有???
      

  11.   

    没有...Oracle官方文档中也只发现了oci的例子,thin方式下的例子我暂时没有找到,正在烦恼中~~~~~
    我再看看能不能找个比较全的文档我已经加二位为好友了,这个问题我会一直关注的,望大家不吝指导
      

  12.   

    没有...Oracle官方文档中也只发现了oci的例子,thin方式下的例子我暂时没有找到,正在烦恼中~~~~~
    我再看看能不能找个比较全的文档我已经加二位为好友了,这个问题我会一直关注的,望大家不吝指导
      

  13.   

    第一点看了些资料,有点眉目,今天忙于其他事,还未调试,感觉和这个链接有些类似:
    http://forums.oracle.com/forums/thread.jspa?threadID=279238
    第二点在定义table类型时取名o_t_cust,然后在java调用
    cstmt.registerOutParameter(5, OracleTypes.ARRAY,"o_t_cust"); 
    执行是抛出无效的名称模式,但是把名称改为大写竟然通过了,O_T_CUST!我猜可能oracle类库中的一些限制吧。现在又出现第三个问题了,table类型数据已经可以取出,但如果是中文出现乱码,全是???,
      

  14.   

    乱码的问题确实没有尝试过,一直使用英文。
    也确实没有注意到楼上所说的类型名大小写的问题。
    不过感觉上是你说的意思。
    因为Oracle的数据字典中所有的类型名和对象名都是大写的。
      

  15.   

    刚才试验了一下
    1、table的类型名确实必须大写,个人认为是JDBC在Oracle数据字典中查询时没有做大小写不敏感化的工作(不过这也正常)。
    2、我的10G使用UTF8的字符集,没有出现乱码。感觉上是oracle字符集在Java端显示不正常的问题。
      

  16.   

    忘记了说,乱码分插进去数据库之前就是乱码, 和插进去是中文读出来后变乱码两种情况,
    如果是前者需要用到java中的encode方法转换
      

  17.   

    楼上两位,这个字符集是哪个配置文件中设置了?或是改那个参数?
    我是tomcat5.0+oracle10g
      

  18.   

    如果从数据库到程序,一直坚持使用utf8,应该不会乱码的楼主周末也加班这晚?要注意休息啊
      

  19.   

    因为数据库的遍码是在创建数据库的时候指定的。
    专码比较复杂,但并非没有方法。(由于修改错的话误后果严重,所以要慎用)
    如果可以还是应用端向数据提供端统一一下比较好。
    查询Oracle的字符集可以使用下面的SQL:
    select userenv('language') from dual
    服务器字符集环境:select * from nls_database_parameters
    客户端字符集环境:select * from nls_instance_parameters推荐给你两个连接:
    http://edu.yesky.com/edupxpt/185/2143685.shtml
    http://blog.csdn.net/annicybc/archive/2006/06/13/794965.aspx
      

  20.   

    这个问题是很奇怪,不仅仅是中文所有字符除了数字都是乱码,不知道doer_ljy你在取table类型时有没有什么转换?我如果不用table类型取数据,中英文和其他符号都可以
    比如:  procedure p_test(
        i_month IN number,
        o_data OUT varchar2
      )as
      begin
        o_data := '成功';
      end;