利用Java存储过程沟通SQLXMLJavaJEE和Web服务
存储过程(stored procedure)允许将运行于数据库层中的持久性逻辑与运行于中间层中的商务逻辑有效地分离开来这种分离可以降低整个应用程序的复杂性并提供其重用性安全性性能和可伸缩性
但是妨碍存储过程广泛采用的一个主要障碍是不同数据库厂商使用各种专有的且依赖于数据库的实现语言使用基于Java的存储过程可以解决这一问题Oracle已经实现了ANSI标准这些标准规定了从SQL中将静态Java方法作为过程或函数进行调用的能力这种实现被简单地称作Java存储过程
在本文中你将了解基于Java的存储过程如何帮助简化商务逻辑提高其性能并扩展数据库的功能本文将介绍Oracle如何在数据库内启用基于Java的存储过程还会介绍Java存储过程如何访问数据以及如何创建基本Java存储过程
选择PL/SQL还是Java
在考虑Oracle存储过程时你可能会想到PL/SQL不过从Oraclei开始Oracle已经在数据库中支持Java从而为存储过程提供了不同于PL/SQL的开放式和可移植的方法我可以听到$ 问题我如何在PL/SQL和Java之间做出选择?我是否应当忘记已经学习的所有PL/SQL相关知识而变为一个Java天地的新手?
两种语言都适用于数据库编程都有自己的优点和弱点在决定选择哪一种语言时可以参考下面根据经验得出的通用规则
对于要求与SQL进行无缝集成的数据库中心来说则逻辑使用PL/SQL从而完成对数据库对象类型和特性的访问
出于与数据库的无关性考虑时可以选择Java作为开放式的语言来取代PL/SQL同时也为了集成和沟通SQLXMLJEE和Web服务等各个领域
OralceJVM使得Java可以运行在数据库中
从Oraclei版本(Oralce)开始Oracle便提供紧密集成的Java虚拟机(JVM)JVM支持Oralce的数据库会话期结构任何数据库对话期都可以在第一Java代码调用时启动一个虚拟上专用的JVM后续的用户可以使用这一已经存在的支持Java的会话期事实上所有会话共享同一JVM代码并保持仅静态的私有状态而垃圾则收集在单个对话期空间内从而为各个Java对话期提供了和SQL操作相同的对话期隔离和数据完整性能力这里不需要为了数据完整性而进行单独的Java支持的过程这一基于对话期的结构提供了较小的内存占用率并使OracleJVM具有与Oracle数据库一样的线性SMP可伸缩性
创建Java存储过程
要将Java方法转换为Java存储过程需要几个步骤包括用loadjava实用程序将Java类加载到数据库中利用调用规范(Call Spec)发布Java方法将Java方法参数类型和返回类型映射到其SQL的对应部分下面部分说明如何完成这些步骤
我将使用一个简单的Hello类它有一个方法Helloworld()返回字符串Hello world
public class Hello
{
public static String world ()
{
return Hello world;
}
}
Loadjava 实用程序
Loadjava是加载Java源文件Java类文件和Java资源文件的实用程序它可以用来验证字节码并将Java类和JAR文件布置到数据库中它既可以通过命令行调用也可以通过包含于DBMS_JAVA类中的loadjava()方法调用为了加载我们的Helloclass示例输入
loadjava user scott/tiger Helloclass
从Oraclei版本开始loadjava允许通过为包含在被处理的类中的方法创建相应的Call Specs来自动将Java类发布为存储过程Oracle为开发测试调试和布置Java存储过程提供了Oraclei JDeveloper
The Resolver Spec
基于JDK的JVM在列于CLASSPATH中的目录中查找类引用并对其进行解析因为Oracle数据库类存在于数据库模式中所以OracleJVM利用数据库解析器(resolver)通过列于Resolver Spec中的模式查找并解析类引用与CLASSPATH不同(CLASSPATH可以应用于所有的类)Resover Spec根据每类的情况进行应用缺省解析器首先在加载类的模式中搜寻类然后在公共同义词(public synonyms)中搜索
loadjava resolve <myclass>
你可能需要指定不同的解析器也可以在使用loadjava时强制进行解析从而在布置时确定可能在以后运行时发生的任何问题
loadjava resolve resolver ((* SCOTT) (foo/bar/* OTHERS)
(* PUBLIC))
Call Spec和存储过程调用
为了从SQL中调用Java方法(以及从PL/SQl和JDBC中调用)必须首先通过Call Spec发布公共静态方法它为SQL定义方法采用的参数以及返回的SQL类型
在我们的例子中我们将利用SQL*Plus连接到数据库并为Helloworld()定义一个顶级Call Spec
SQL> connect scott/tiger
SQL> create or replace function helloworld return
VARCHAR as language java name Helloworld () return
javalangString;
/
Function created
可以像下面这样调用Java存储过程
SQL> variable myString varchar[];
SQL> call helloworld() into :myString;
Call completed
SQL> print myString;
MYSTRING
Hello world
Java存储过程可以通过其Call Spec从以下各项中进行调用SQL DML语句(INSERT UPDATEDELETESELECTCALLEXPLAIN PLANLOCK TABLE和MERGE)PL/SQL块子程序程序包以及数据库触发器Call Spec的美妙之处在于存储过程实现可以从PL/SQL转换为Java反之亦可这一点对于请求者是透明的
Call Spec从实现语言中(PL/SQL或Java)中抽象出调用界面因而使之能够在原有应用程序和新的基于Java/JEE的应用程序之间共享商务逻辑但是在从Java客户程序调用在数据库驻留的Java类时你可能不希望通过PL/SQL包装器(wrapper)在以后的版本中Oracle计划提供一种机制它可以使开发人员略过Call Spec
高级数据访问控制
Java存储过程可用于控制和限制对Oracle数据的访问其方法是只允许用户通过存储过程管理数据而存储过程在其调用者的权限内执行而不能对表本身进行访问例如你可以在特定时间内禁止更新数据或者使管理者只具有查询工资数据的权利而不能进行更新或者记录所有的访问并通知某一安全机构
原有应用程序与JEE应用程序之间的数据逻辑共享
因为原有应用程序与JEE应用程序都通过Call Spec调用存储过程所以JEE和非JEE应用程序可以共享相同的数据逻辑由于有了Call Spec所以不用考虑所用的是何种实现语言(无论是PL/SQL还是Java)该数据逻辑都可以共享
为BMP实体Bean自动生成主关键字
在对EJB实体bean应用BMP时一个bean实例可以由自动生成的与新插入的数据相关联的主关键字惟一确定它是ejbCreate()的返回值可以利用一个插入相应数据的存储过程在一个数据库操作中检索ejbCeater()中的该值并检索或计算主关键字作为另一种方法也可以利用JDBC的RETURN_GENERATED_KEYS特性以一个SQL语句插入该数据并检索相应的关键字(或ROWID)但是存储过程方法在各个JDBC驱动器版本和数据库之间更具可移植性
可以用以下三个步骤实现这一模式
创建一个Java存储过程在公共GenPk类中定义一个公共静态Java方法insertAccount()此方法将插入数据计算惟一的关键字(通过发出一个序列号)并返回计算出的关键字作为主关键字
定义Call Spec
CREATE OR REPLACE PROCEDURE insertAccount(owner IN
varchar bal IN number newid OUT number)
AS LANGUAGE JAVA NAME GenPKinsertAccount(
javalangString []);
/
在ejbCreate()内调用存储过程
Public AccountPK ejbCreate(String ownerName int balance) throws CreateException
{
try {
CallableStatement call = connprepareCall{
{call insertAccount(? ? ?)}};
return new AccountPK(accountID);
}
}
为CMP实体Bean定制主关键字查找器
查找器方法(Finder methods)用于检索已存在的EJB实体bean实例主关键字查找器使你能够检索惟一标识的EJB实例对于CMP实体beanEJB容器根据声明描述自动生成主关键字查找器findByPrimaryKey()方法但是在某些情况下可能需要更多的控制例如可能需要专门的查找器如findByStoredProcKey()在这些情况下你可以结合使用Java存储过程和对象关系框架(如Oraclei应用服务器[OracleiAS] TopLink)来实现定制的主关键字查找器方法在将EJB查找器定义为REDIRECT或NAMED查找器后TopLink将生成一个SQL查询用于检索bean实例
数据驱动的EJB调用
在数据驱动体系结构中商务逻辑调用可以作为数据库操作(如插入更新或删除)的结果来触发实现该数据逻辑的Java存储过程可以被声明为数据库触发器用以调用运行于中间层JEE应用服务器的EJBEJB的调用既可以采用JEE兼容的服务器通过Interoperable InterORB Protocol(IIOP)标准远程方法调用(remote method invocationRMI)