数据库

本类阅读TOP10

·SQL语句导入导出大全
·SQL Server日期计算
·SQL语句导入导出大全
·SQL to Excel 的应用
·Oracle中password file的作用及说明
·MS SQLServer OLEDB分布式事务无法启动的一般解决方案
·sqlserver2000数据库置疑的解决方法
·一个比较实用的大数据量分页存储过程
·如何在正运行 SQL Server 7.0 的服务器之间传输登录和密码
·SQL中两台服务器间使用连接服务器

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
ORACLE自带的JDBC源代码解析

作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站

        大凡使用过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 同目录);

        下面我就把文件夹\samples\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:[email protected]




相关文章

相关软件