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中怎么获取这个对象数组,并逐字段读 出来了??
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中怎么获取这个对象数组,并逐字段读 出来了??
类型定义:
-------------------------------------------------------
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();
----------------------------------------------------
如果在thin连接方式下,
我估计会在stmt.execute()这一行抛出异常原因在于java代码在thin连接方式下没有合适的对象接收table类型,即这一句
stmt.registerOutParameter(1,OracleTypes.ARRAY,"T_OBJ")中使用的OracleTypes.ARRAY类型不能正常接收存储过程的table
java中的Array对象我也试过,一样不能正常接收
当时我甚至想过重写驱动包,但是这个方案由于复杂和稳定性的考虑被否定了这个问题我作过浅短探究,
结论是在服务器端的话使用oci的连接方式是可行的,
调用时记得使用OracleCallableStatement对象而非CallableStatement就可thin方式下我的方法是创建临时表(临时表往往没有我们想象的那样麻烦),
然后使用游标返回结果,而不是table类型当时我也搜索了好多网页,浪费了很多时间
但愿楼主少走弯路,能早日找到可行的解决办法
我只是不想把我是沿用的代码完整的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();
}
}}
其实很多时候去google或者baidu需要的只是倒不如看看Oracle提供的官方文档。
建议看看Oracle官方提供的JDBC的资料,其中专没有oracle对象(Object)、可变数组等在JDBC中如何使用的介绍。
当然,本人也是第一次尝试如此调用,解决方法可能会有与本地环境高度聚合的情况。
愿意与大家探讨!
stmt.registerOutParameter(1,OracleTypes.ARRAY,"T_OBJ");
报
Exception in thread "main" java.sql.SQLException: 无效的名称模式:Doer.T_OBJ
运行的时候我加了我本地Scheme的前缀,当然不是Doer,所以我也报的错相应地改了下我觉得,
应该是java不认类型T_OBJ,
楼上能指点一下吗?我很想搞清这个问题有点怀疑是我的ojdbc14.jar了不知道楼主解决了没
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都是有效的。
也能修改数据库和打印结果,
虽然我的存储过程和你的不一样,
但是意思是一样的,就是调用返回table这个自定义的table类型无论我把它定义在包里面不是包外面java都不认,我都服了
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
数据库通过JNDI连接,就会报出ClassCastException异常,如果直接用JDBC连接就不会抛出这个异常,原因虽然找到仍不知道如何用JNDI才能通过,大家继续讨论呵?这个错误解决后,又报错,与lpc19598188 相同错误,
抛出:无效的名称模式,
单独执行存储过程也是可以的。
不知lpc19598188 解决了没有???
我再看看能不能找个比较全的文档我已经加二位为好友了,这个问题我会一直关注的,望大家不吝指导
我再看看能不能找个比较全的文档我已经加二位为好友了,这个问题我会一直关注的,望大家不吝指导
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类型数据已经可以取出,但如果是中文出现乱码,全是???,
也确实没有注意到楼上所说的类型名大小写的问题。
不过感觉上是你说的意思。
因为Oracle的数据字典中所有的类型名和对象名都是大写的。
1、table的类型名确实必须大写,个人认为是JDBC在Oracle数据字典中查询时没有做大小写不敏感化的工作(不过这也正常)。
2、我的10G使用UTF8的字符集,没有出现乱码。感觉上是oracle字符集在Java端显示不正常的问题。
如果是前者需要用到java中的encode方法转换
我是tomcat5.0+oracle10g
专码比较复杂,但并非没有方法。(由于修改错的话误后果严重,所以要慎用)
如果可以还是应用端向数据提供端统一一下比较好。
查询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
比如: procedure p_test(
i_month IN number,
o_data OUT varchar2
)as
begin
o_data := '成功';
end;