改进的Oracle Jpublisher可以将数据库实体映射到Java和Web服务
编写客户端和中间层的Java与JEE应用程序来表示数据库实体如用户定义的SQL对象类型和集合类型时如果你需要手工完成所有编码这将是非常具有挑战性和易于出错的工作另一种办法则是你可以使用Oracle JPublisher工具来完成该工具自动根据你输入的命令行(或根据在Oracle JDeveloper集成开发环境下的鼠标点击)自动产生相应的Java类
本文中我将概要介绍JPublisher并描述它是如何简化将数据库实体映射到Java的过程包括你无法从Java Database Connectivity (JDBC)直接使用的类型然后我将展示如何通过一或两个JPublisher命令将数据库的操作和商务逻辑映射到你的Java客户端JEE组件和Web服务客户端最后我将描述JPublisher如何简化从数据库内部调用外部Web服务的过程
Jpublisher概述
Oracle JPublisher是一个用于在Java和SQL之间转换和交换结构化对象数据的工具它还可以访问其他的数据库资源如PL/SQL包和Java存储过程它生成Java类来表示数据库实体如SQL对象和操作PL/SQL包和过程以及服务器端Java类你可以通过JDBC在你的Java客户端servletJavaServer Pages (JSP)Enterprise JavaBeans (EJB)和Web服务中使用这些生成的类
JPublisher 可以生成表示以下数据库实体的类
用户定义的SQL对象类型对于每个对象类型JPublisher为表示该对象的类生成一个typejava文件它提供访问程序方法用以获取和设置该对象类型的每个属性还有如果你的对象类型包含了作为存储过程而实现的方法则JPublisher将生成封装器方法在对象实例上调用这些方法
对象引用类型(REF 类型) 对于一个SQL对象引用类型JPublisher生成一个typeRefjava文件来建立该Java对象类型的引用模型它包括通过一个对象引用来访问实际的对象值的方法
用户定义的SQL集合类型对于每个集合类型JPublisher为表示该集合的类生成一个typejava文件对于嵌套的数据表生成的类具有作为整个数组来获取和设置嵌套的数据表的一些方法以及用于获取和设置该数据表中各个元素的一些方法
用户定义的OPAQUE类型每当JPublisher遇到一个没有提供其相应类型的SQL OPAQUE类型时它都会生成一个typejava文件来发布一个Java封装器类OPAQUE的有效负荷以字节数组(byte array)来表示可以从生成的封装器的子类中进行处理
PL/SQL BOOLEAN PL/SQL BOOLEAN被映射到Java Boolean类型这要求有SYSSQLJUTL包该包是由数据库(JPublisher生成的代码要在其中运行)中的sqljutilsql脚本来安装的这个脚本默认安装在Oracle Database g中
PL/SQL RECORD和TABLE类型对于RECORD和TABLE类型JPublisher生成相应的SQL对象(对于RECORD类型)或SQL VARRAY类型(对于TABLE类型)以及用于在PL/SQL和SQL类型之间进行映射的转换函数
PL/SQL INDEXEDBY数据表如果你使用Oracle Database g 的JDBC Oracle Call Interface (OCI)驱动程序并且需要发布已有索引的标量数据表那么你可以直接在Java和这些类型(以Java数组表示)之间进行映射
运行JPublisher实用工具
要在数据库中你想转换为Java类的用户定义的数据类型和PL/SQL包上运行JPublisher你必须建立一个数据库连接以便能对你映射的SQL类型和PL/SQL包进行访问为此可以使用user和url选项如下例所示
% jpub user=scott/tiger url=jdbc:oracle:oci:@
% jpub user=scott/tiger url=jdbc:oracle:thin:@host:port/
servicename
第一个例子使用了Oracle JDBC OCI驱动程序第二个使用了Oracle JDBC Thin驱动程序下面的例子建立在Order Entry (OE)模式的基础上该模式是Oracle Database g中一些示例模式的一种假设OE模式的口令是OE使用以下命令来发布SQL对象类型CATEGORY_TYP其中CategoryTyp是相应Java类的名字
% jpub user=OE/OE url=jdbc:oracle:oci:@
sql=CATEGORY_TYP:CategoryTyp
sql选项指定将要发布的类型和类包
Oracle JPublisher生成并编译相应的Java类
映射数据库操作
在这一部分我将对PL/SQL包到Java的手工映射与JPublisher方法进行比较和对照我的例子中使用了一个PL/SQL特有的类型该类型无法从Java (本例中是PL/SQL RECORD)直接访问而JPublisher则提供了附加支持
create or replace package action
as type emprec
is record (name varchar()
age number);
procedure foo (hired timestamp
emp in out emprec);
end;
/
假设你想将ACTION包映射到一个Java类的ActionJDBC支持从TIMESTAMP到javasqlTimeStamp的映射然而你并不想使用JDBC支持的映射而是想从TIMESTAMP映射到Date相应的Java foo方法将有如下定义
public void foo(javautilDate hired EmpRecSql[] emp_inout)
手工方法下面的一些步骤概括了你可以如何为这个ACTION包示例手工设置PL/SQL到Java的映射
为PL/SQL RECORD类型EMPREC创建一个SQL对象类型例如EMPREC_SQL
为你创建的SQL类型创建一个Java类型例如为SQL类型EMPREC_SQL创建Java类型EmpRecSql
在Java中将每个参数转换为一个对应的Java类型例如将SQL TIMESTAMP转换为Java Date
通过JDBC将每个IN或IN OUT参数传递给一个PL/SQL块例如将EmpRecSql和TimeStamp传递给foo
在PL/SQL块中将每个IN和IN OUT参数转换为PL/SQL存储过程的正确类型例如将EMPREC_SQL转换为EMPREC
调用PL/SQL存储过程
在PL/SQL中将每个OUT参数IN OUT参数或函数结果从JDBC不支持的类型转换为JDBC支持的相应类型例如将EMPREC转换为EMPREC_SQL
从PL/SQL块返回每个OUT参数IN OUT参数或函数结果
在Java中将每个OUT参数IN OUT参数或函数结果从JDBC支持的类型转换为它不支持的类型例如从TimeStamp转换为Date
Oracle JPublisher方法以下的JPublisher命令直接发布ACTION包
%jpub u scott/tiger s action:Action
style=webservices
outarguments=array
plsqlfile=actionWrapsql
请注意style=webservices选项指定从TimeStamp到Date的映射outarguments= array表示OUT参数通过只有一个元素的数组来传递
JPublisher产生你必须在使用JPublisher生成的代码之前要执行的PL/SQL封装器脚本这个脚本包含了对应PL/SQL EMPREC类型的SQL类型EMPREC_SQL的定义以及EMPREC和EMPREC_SQL之间的转换函数同时该脚本还包含了一个针对PL/SQL存储过程foo的封装器
以下命令将执行生成的脚本
% sqlplus scott/tiger @actionWrapsql
这就算完成了两相比较JPublisher只需两个命令就可以完成ACTION包的PL/SQL到Java映射而手工方法中却需要很多个命令
以下是对JPublisher为ACTION PL/SQL包到Java映射生成的每个文件的简单描述
Actionjava 为ACTION包生成的Java基类
ActionBasejava从ActionBase扩展来的Java用户子类
ActionUserjava 从ActionBase扩展来的Java类包含Java类型映射如从TimeStamp到Date
ActionEmprecjava 为EMPREC_SQL生成的Java接口
ActionEmprecBasejava为EMPREC_SQL生成的Java基类
ActionEmprecUserjava 提供ActionEmprecBase的Java用户子类
ActionEmprecUserRefjava EMPREC_SQL的REF类型的Java类型
actionWrapsql定义了EMPREC的SQL类型的SQL和PL/SQL脚本以及EMPREC和SQL类型之间的转换函数
数据库作为Web服务提供者
Oracle Database g提供了一个新的JPublisher特性用以支持数据库Web服务Oracle Database g与Oracle Application Server g的结合允许你将PL/SQL包和存储过程SQL查询SQL数据操作语言(DML)语句以及服务器端Java类发布为Web服务JPublisher生成的类可以通过Oracle Application Server Web Services Assembler工具作为Web服务而公布
发布SQL查询或DML语句JPublisher可以将具体的SELECTUPDATEINSERT或DELETE语句发布为一个Java类的方法这个类也可以作为Web服务而发布
样式文件在发布服务器端Java类时JPublisher使用说明Java到Java类型映射的样式文件来确保生成的类可用于Web服务
生成Java接口JPublisher可以生成Java接口和类这就避免了手工生成Java接口来表示用以生成Web服务描述语言(WSDL)内容的API
所支持的SQL类型以下的SQL类型可以在数据库Web服务签名中发布各种简单SQL类型包括DATESQL对象类型SQL VARRAY类型SYSXMLTYPE和REF CURSOR
数据库作为Web服务消费者
当数据库作为Web服务消费者时Web服务客户端代码采用SQLPL/SQL或Java编写并在数据库中运行用以调用外部Web服务对于在数据库中运行以访问其他Web服务的代码你必须能够调用这些服务你可以使用手工方法进行简单对象访问协议(SOAP)的编程或者通过JPublisher以下步骤将帮助你通过JPublisher来构建你的第一个数据库Web服务消费者
第一步确认数据库的安装在Oracle Database g中在数据库安装时应该装入了[Oracle_Home]/sqlj/lib的sqljutljar库和utl_dbws_jserverjar库以及SYSUTL_DBWS包
第二步生成并装入客户端代理以及Java和PL/SQL封装器JPublisher将生成Web服务客户端代理代码的任务完全自动化将其编译放入Java归档(JAR)文件并装入到数据库中 使用以下格式来生成代理代码
% jpub
proxywsdl=URL_of_Web_Service_WSDL
user=username/password
另外如果它与WSDL本身所提供的不相同则你可以指定
endpoint=external_Web_Services_URL
如果与通过JDBC OCI驱动程序访问的默认数据库实例不相同则你还可以指定url=JDBC_database_URL以下例子使用了多个选项
% jar xvf dist/javacalloutjar
METAINF/HelloServiceEJBwsdl
% jpub proxywsdl=METAINF/
HelloServiceEJBwsdl
dir=genproxy
package=javacallout
user=scott/scott
//localhost:/
javacallout/javacallout
proxywsdl选项指定了WSDL文件JPublisher将为它生成静态Java代理类Java和PL/SQL封装器以及PL/SQL脚本
dir选项为生成的代码和脚本指定了根目录
package选项为生成的Java代码指定了包的名字
代码生成后JPublisher自动将以下文件装入数据库中
genproxy/javacallout这个目录下的Java类由JPublisher调用的Web服务WSDL编译工具生成
genproxy/HelloServiceEJBJPubjavaHelloServiceEJBJPubjava类将方法sayHello()定义为一个静态的Java方法
genproxy/plsql_wrappersql这是Web服务客户端(HelloServiceEJBJPubjava)的PL/SQL封装器
genproxy/plsql_droppersql它用来删除plsql_wrappersql定义的PL/SQL类型和包
genproxy/plsql_grantsql它(运行在SYS下)用来为Java客户端代理分配必要的权限以调用Web服务
genproxy/plsql_revokesql它用来取消plsql_grantsql所分配的权限
genproxy/jpub_proxyloadlog这是用于装入生成的Java文件和安装plsql_wrappersql脚本的日志文件
为了禁止JPublisher将生成的代码装入到数据库中你可以指定选项proxyopts =noload使用静态客户端代理的优点是你可以简化在你的Java代码中引用端口类型实例方法而无需担心如何编排(marshal)或反编排(unmarshal)来自SOAP消息的个别参数 下一步
第三步分配权限脚本plsql_grantsql用于SYS给SCOTT分配执行装入的客户端代理时所必需的权限
SQL> conn / as sysdba
SQL> @genproxy/plsql_grantsql
第四步调用外部Web服务要从数据库调用外部Web服务声明和运行run_plsql_proxysql脚本或运行以下的PL/SQL块
SQL> set serveroutput on
SQL> declare x varchar();
begin
x:=JPUB_PLSQL_WRAPPERsayHello(
Hello from database);
dbms_outputput_line(x);
end;
/
第五步清除使用SQL*PLUS删除PL/SQL封装器并取消分配的权限
SQL> conn scott/tiger
SQL> @genproxy/plsql_droppersql
SQL> conn / as sysdba
SQL> @genproxy/plsql_revokesql
使用dropjava工具从数据库中删除装入的Java类
dropjava u scott/tiger
genproxy/wsdlGeneratedjar
结论
JPublisher使Java开发人员免于复杂的学习以及掌握手工创建Java数据库访问程序的很多逻辑细节和麻烦此外Jpublisher还简化了将数据库操作作为Web服务发布的过程和从数据库内部使用外部Web服务的过程