分享
 
 
 

ORACLE自带的JDBC源代码解析

王朝oracle·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

大凡使用过JDBC连Oracle的人都会知道这样一个事实:我们需要的库文件classes12.zip存在于$ORACLE_HOME/jdbc/lib目录下(但仍有部分菜鸟每每在论坛上求此库文件,

真是辛劳);但很少有人知道ORACLE还为我们预备了使用jdbc的示例,它存在于 $ORACLE_HOME/jdbc/demo/demo.zip 中。

前一段时间,我学习ORACLE的OOP技术,很受触动。当时我想:JDBC中一定存在某些OO技术以支持它。很久都没有找到合适的例子,最后在ORACLE的安装目录下找到它。真可谓是:踏破铁鞋无觅处,得来全不费工夫。

约定:

1、假如出现 Java.lang.UnsatisfiedLinkError: do_open,则你需要把 DriverManager.getConnection() 方法的 url 修改成 jdbc:oracle:thin:@127.0.0.1:1521:oradb,具体原因未知;

2、假如出现 java.sql.SQLException: 不支持的字符集: oracle-character-set-852,则你需要把 nls_charset12.zip加入你的工程中(此文件与 classes12.zip 同目录);

下面我就把文件夹 amples\oci8\object-samples下的文件做一个具体的功能描述:

1、PersonObject.java

这个例子演示了表 people 中存在ADT字段 empid,其类型为 PERSON,而且类型 PERSON中存在ADT字段 home,其类型为 ADDRESS,而且类型 ADDRESS是一个ADT。

假如使用常规SQL语句,其插入语句与在sql/plus中无异,即:使用构造函数嵌套构造。

另有一种方法,使用 STRUCT 的构造函数 STRUCT(StructDescriptor, Connection, Object[]) 构造出一个STRUCT对象,即一个ADT对象。同时,假如有嵌套则需要嵌套构造ADT对象。最后通过 PreparedStatement的 setObject方法指定ADT对象即可。

读取数据时则采用与上述方法相逆的办法:假如是简单类型,则直接读取;假如是ADT,则使用ResultSet的getObject(),再强制转换成STRUCT,然后调用STRUCT的getAttributes()方法取得 Object[] 类型数据,如是递归。

2、SQLDataExample.java与EmployeeObj.java

此例与1中相似,也是对ADT的处理,不同的是类型没有嵌套。

比较而言,2比1的代码简洁了很多,不过也是付出了代价:为类型 EMPLOYEE 抽象出一个类EmployeeObj,它实现了SQLData接口,并重写了三个方法(必须的)。

前台的调用比1中的第二种方法简洁了很多,只需要直接使用PreparedStatement的 setObject方法指定ADT对象即可(不过需要指定其类型为OracleTypes.STRUCT)。读取时也可直接使用OracleResultSet的getObject()并强制转换成EmployeeObj对象即可。

真可谓是:有得必有失!!

另,此例中有几处需要注重的地方:

2.1 EmployeeObj.java中的 import oracle.jdbc2.*; 改成 import oracle.jdbc.*; 原因未知;

2.2 SQLDataExample.java 中的 Dictionary map = conn.getTypeMap(); 改成 java.util.Map map = conn.getTypeMap(); 原因:NOTE: This class(指的是Dictionary) is obsolete. New implementations should implement the Map interface, rather than extendidng this class.(来源:javadoc);

2.3 SQLDataExample.java 中的 pstmt.executeQuery(); 改成 pstmt.executeUpdate(); 更合理些,因为这是更新而非查询(不改也不会影响功能,只是建议);

3、CustomDatumExample.java与Employee.java

此例与2完全相同。

不同的是采用了另外一种抽象技术,并实现了接口CustomDatum 与 CustomDatumFactory,并重写了二个方法toDatum()与create()。在前台访问数据时亦有少许不同:采用了OracleResultSet的getCustomDatum()方法并把它强制转换成Employee。从外观上看,2中SQLData接口存在于 java.sql.* 包中;而接口CustomDatum 与 CustomDatumFactory则存在于oracle.sql.*包中,可以认为是Oracle公司对自己产品的专门实现。或许有更高的性能、更小的开销?不过3不如2来得直接,个人认为。

4、ArrayExample.java

从文件名可看出,此示例演示的是VARRAY类型。

同1,插入亦有两种方法。一种可直接使用SQL;另外,可使用OraclePreparedStatement的setARRAY方法,构造ARRAY的过程与构造 STRUCT 无异。数据的读取过程与此相反:先使用OracleResultSet的getARRAY()方法取得ARRAY对象,再调用此对象的getArray()方法并强制转换成对象数组,然后对此数组操作即可。

5、PersonRef.java与StudentRef.java

不知是不是ORACLE与我们开玩笑,这两个文件除了类名不同外,其余一切相同。

这个例子给我们演示的是对象表的概念。对象表的插入与普通表没有任何不同,数据的读取首先体现在其SQL上,需要使用REF函数,然后调用ResultSet的getObject()方法并强制转换成REF对象,再利用此对象的getValue()并转换成STRUCT对象,再利用此对象 的getAttributes()方法得到Object[],然后对此数组操作即可。

6、RefClient.java与GenREF.java

This sample demonstrates using REF over two different Sessions.

类GenREF用来封装REF对象所指向的类型及其二进制内容。程序先Materialize into GenREF,然后在另一会话中De-materialize REF from GenREF,下面就与处理REF相同:利用此对象的getValue()并转换成STRUCT对象,再利用此对象 的getAttributes()方法得到Object[],然后对此数组操作即可。

7、FileExample.java与PLSQL_FileExample.java

此示例使用 BFILE 数据类型,Contains a locator(定位器) to a large binary file stored outside the database。数据插入时需要使用函数 bfilename,这个函数需要目录对象,此对象需要使用create Directory mydir来创建(此用户需具有CREATE ANY DIRECTORY系统权限)。我曾在这个地方有个大教训:按着步骤做,可在读取时总是提示我没有此目录!!最后,我把BFILENAME函数的第一个参数(即目录名)大写就好了。原因:目录名在函数中区分大小写,虽然我们创建它时用的是小写,可到了数据库中后就自动变成了大写。

读取BFILE类型的数据时,首先通过其getBinaryStream()方法得到二进制的输入流,然后操作这个输入流就可以了。The limitation is your imagination。

PLSQL_FileExample.java实现的功能与上述的相同,只不过所有针对BFILE的操作都是通过调用pl/sql匿名块来完成的,并使用了OracleCallableStatement。假如没有必要,使用前者即可。

8、LobExample.java与PLSQL_LobExample.java

此示例使用了CLOB和BLOB数据类型。

插入数据时,需要分别通过getBinaryOutputStream()和getCharacterOutputStream()得到二进制输出流和字符输出流,然后就是针对此输出流的操作了,与传统的 java I/O 相同。

读取数据时,需要分别通过getBinaryStream()和getCharacterStream()得到二进制输入流和字符输入流,然后就是针对此输入流的操作了,与传统的 java I/O 相同。

PLSQL_LobExample.java实现的功能与上述的相同,只不过所有针对CLOB和BLOB的操作都是通过调用pl/sql匿名块来完成的,并使用了OracleCallableStatement。

假如没有必要,使用前者即可。

注:7、8的第二个示例中均使用到了dbms_lob程序包。

上面我仅对ORACLE给我们提供的demo的极小的一部分给出了解释,并加入我自己的看法。我也是想通过这篇文章,起到抛砖引玉的作用,希望广大网友多对产品的示例进行分析,从而得到最原汁原味的代码。

你的意见,我愿意听!! email:zbdlmxc@163.com

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有