用SQLJ开发数据库

来源:互联网 发布:网络服务器机柜cqwsjg 编辑:程序博客网 时间:2024/06/01 10:07

--作者

SQLJ开发数据库4

Java ( SQLJJDBC)Oracle数据库中的PL/SQL比较:

   Oracle数据库应用程序中的使用的Java还不能够替代PL/SQLJavaPL/SQL相辅相成,Java (SQLJ/JDBC)有下列优于PL/SQL的地方

Java能够提供重要的性能优势,Java存储过程要快5到100倍,这主要取决于程序中使用的数学操作符和数据类型。

理论上说,Java存储过程可以很容易的转化成运行在其它数据库上的存储过程。

Java程序可以在一个复杂的应用程序的任何一层上配置∶在客户端上,在中间层的应用程服务器上或在数据库服务器本身中。

Java ( SQLJ/JDBC)也同样分享PL/SQL的不足之处:PL/SQLOracle数据库服务器紧密地结合起来,Oracle在近20年的时间中不断的改进PL/SQL,而Java只在1998年的时候才被引进Oracle 8i

PL/SQL数据类型等价于Oracle本地数据类型,所以不需要进行数据类型的换算。在另一方面,JDBC提出在Java代码和SQL语句之间插入一个普通的层,而SQLJ是又一个层。

PL/SQL工作性能比Java好,因为是以数据库为中心编程:PL/SQL存储过程比Java程序快1.5倍(对于OLTP联机事务处理)到2.5倍(用于批处理)

此外,Java程序要使用比PL/SQL更多的CPU资源CPU额外开销的增加可能是因为要进行一个比较长的编码过程以及从OracleJava的额外的数据类型转换。

   一个两者兼顾达到最好效果的解决方案

   Oracle提供了一个理想的环境用于利用PL/SQLJava语言两者的优点。在一方面,PL/SQL程序可以调用SQLJJDBC存储过程,允许你构建基于组件的EJBCORBA应用程序。现有的Java类库可以很容易地被利用,并通过使用PL/SQL调用规范来整合入数据库代码开发过程中。在另一方面,Java程序可以通过JDBC或者SQLJ调用PL/SQL存储过程,函数和匿名的程序块。我下面想一一详细介绍,SQLJ提供用于调用下面这些内容的语法:

   存储过程:使用CALL操作符调用UpdateSalary程序


#sql { CALL UpdateSalary };
函数:<0} {0>to call the GetName() function using the VALUES operator: <}0{>使用VALUES操作符调用GetName()函数<0}
{0>String name; <}0{>String name;<0}
#sql { name = { VALUES GetName() };
or by using the SET operator:
String name;
#sql { SET :name = GetName() };
{0>Anonymous PL/SQL blocks: <}0{>
匿名的PL/SQL程序块<0}
#sql { [DECLARE ...]
BEGIN ... END; };

   需要注意的是影响决定使用什么语言的因素,不仅由执行效果决定--说得更精确些,一个现今应用程序开发过程中的主要因素,而且由程序员劳动生产率、可获得的专家的意见和轻便性决定。幸亏对于数据库开发人员,不必在几种语言中选来选去,你可以很容易地把Java ( SQLJJDBC)PL/SQL存储程序混合搭配进一个数据库来取得一个两者兼顾达到最好效果的解决方案。

 

SQLJ开发数据库5

   SQLJ语言元素

   SQLJ是正在发展的工业标准语言,允许你使用独立于数据库代码的Oracle存储过程,可以很容易地移植到其他的可使用Java的数据库平台。知道连接上下文,迭代程序,可执行语句和主表达式的情况,那么你就可以把一些实际的SQLJ语句用到现实的应用程序中。

   在前文中,我描述了SQLJ是什么,比较了PL/SQLJDBC,并且研究了SQLJ的好处。 在本文中,我将研究一下SQLJ编程语言的基础这样你就可以在现实的应用程序中使用SQLJ了。SQLJ程序是一个使用嵌入式结构化询问语言语句的规则的Java程序,以一个#_sql标记开始并以一分号结束。有二类SQLJ语句∶声明和可执行语句。声明语句声明了连接上下文和迭代程序。连接上下文用来建立数据库连接,而迭代程序被用来存储由SQL查询返回的结果集;可执行语句执行嵌入式结构化询问语句和PL/SQL程序块。因为SQLJ程序将要被翻译然后通过JDBC运行,任何JDBC驱动程序支持的SQLJ语句可能内嵌在一个SQLJ可执行语句中。可执行语句可能同时包含主表达式,在Java程序和数据库之间通过Java变量交换信息

   Oracle JDBC驱动程序

   Oracle提供下列JDBC驱动程序

   客户端瘦驱动程序是一个100%Java驱动程序,用于在没有安装Oracle的客户端。Oracle推荐使用小应用程序。当Java小应用程序运行的时候,它可以下载到浏览器中。

   OCI驱动程序( OCI8OCI7)是用于安装了Oracle客户端程序的客户端。Oracle JDBC OCI驱动程序通过调用Oracle调用界面( OCI)直接从Java访问数据库,提供与不同版本的Oracle7,Oracle8和8i之间最大的兼容性。这些驱动程序要求Oracle客户程序安装Net8服务器端瘦驱动程序提供了与客户端瘦驱动程序相同的函数,但是在一个Oracle数据库内运行并且访问一个远程数据库。这对于从一个担任中间层的Oracle服务器上访问远程Oracle服务器是很有用的,或者,更简单一些来说,从一个层内访问另一个Oracle服务器,例如从某一个Java存储过程或者EJB内访问Oracle服务器。

   服务器端内部驱动程序,称为KPRBKernel Program Bundled),提供对任何在执行SQL操作的目的Oracle数据库内运行的Java代码的支持。服务器端内部驱动程序允许JServer JVM直接与SQL引擎通信这是一个默认的用于在Oracle 8i/9i服务器上运行SQLJ代码的JDBC驱动程序,这些SQLJ代码用作存储过程,存储函数,触发器,EJBCORBA对象。KPRB JDBC驱动程序非常轻便但是效率高,并且在Oracle JServer内运行特别地能够做到尽善尽美。这就是我们要来写SQLJ存储过程所用的驱动程序。让我们来研究一下描述的SQLJ元素,逐一介绍:连接上下文,迭代程序,可执行语句以及主表达式。

   连接上下文用于单一连接,你可以使用DefaultContext类的一个实例并在构造DefaultContext对象时指定数据库URL,用户名和口令。这是使用Oracle公司提供的oracle.sqlj.runtime.Oracle类的connect()方法的最容易的方法。在本例中,我们将要使用JDBC瘦驱动程序以及用户名"scott"和口令"tiger"来通过端口1521连接MYSERVER服务器上的数据库,在这个服务器里,数据库的SIDORCL
Oracle.connect("jdbc:oracle:thin@MYSERVER:1521:ORCL", "scott", "tiger");
它创建DefaultContext类的一个实例并且把它作为默认连接。并不一定需要直接使用DefaultContext的实例做任何事情。对于多重连接,你可以创建并通过使用Oracle.getConnection ()方法来使用DefaultContext类的辅助实例。在本例子中,你将使用Oracle OCI8驱动程序使用MYSERVER_ORCL作为Oracle服务名,在TNSNames.ora文件中创建做为一个ORCL实例


DefaultContext myContext1 = Oracle.getConnection
("jdbc:oracle:oci8@MYSERVER_ORCL", "scott", "tiger");
DefaultContext myContext2 = Oracle.getConnection
("jdbc:oracle:oci8@MYSERVER_ORCL ", "tom", "bear");

   这段代码创建二个连接上下文实例,它们两个都使用相同的Oracle OCI8驱动程序,但是不同的模式。你可以通过使用为每个语句指定连接模式的方法在两个不同的模式中执行SQL操作。


#sql [myContext1] { SQL statement };
...
#sql [myContext2] { SQL statement };

   在这个程序的结尾,我们需乇赵贔INALLY子句和TRY/CATCH语句块中的连接。


finally
{
#sql [myContext1] { commit };
myContext1.close();

#sql [myContext2] { commit };
myContext2.close();
}
...

 

SQLJ开发数据库6

   迭代程序

   SQLJ程序中,SQL查询返回的结果集可以作为一个迭代程序对象,用来保存数据。迭代程序对象是迭代程序类的一个实例,并且在概念上类似于PL/SQL游标。我们必须执行下面的五个步骤来使用迭代程序处理SQL查询返回的数据。

    声明迭代程序类。

    从迭代程序类声明一个迭代程序对象。

    使用SELECT语句添加迭代程序对象。

    从迭代程序对象中读取数据。

    关闭迭代程序对象。

   有二种类型的迭代程序类

    命名的迭代程序,在这种类型中,Java变量类型和迭代程序列名都必须被指定。

    位置迭代程序,在这个类型中,只有用于从数据库中检索得到的列的Java变量类型需要指定。

   命名迭代程序一个命名迭代程序声明指定了列存取器名和它们的Java类型。

   让我们来演示一下使用这个例程的五个步骤,在本例中我们想检索雇员表Emp中的EnameJobHireDate列,查找工资大于1500的雇员。

   声明迭代程序类


#sql iterator EmpIteratorClass(String Ename, String Job, Timestamp HireDate);

   我们使用Java String类来表示EnameJob列,因为它兼容Oracle VARCHAR2数据库类型。

   java.sql.Timestamp类型用于HireDate( Oracle的日期类型),因为java.sql.Date类型只能保存年份,日期和时间信息,而不能象java.sql.Timestamp一样保存小时,分钟和秒。

   从迭代程序类中声明迭代程序对象

    EmpIteratorClass empIterator;

   使用SQL SELECT语句添加迭代程序对象。

   下列SQLJ语句把Emp表的EnameJobHireDate列中的内容加入empIterator对象


int salary = 1500;
#sql empIterator = {
select Ename, Job, HireDate
from Emp
where Sal > :salary
};

   我们还要声明主变量salary,用于WHERE子句中来标识要从Emp表中返回什么数据。

   记住,通过SQL查询返回的数据库列的名称必须对应于第一步中定义迭代程序列名。从迭代程序对象中读取数据。因为迭代程序对象可能包含多个行,所以我们需要使用一个循环来访问每一行数据,就象我们从PL/SQL游标中读取数据一样。命名迭代程序实现一个next()方法,允许你在迭代程序对象的数据之间移动。此外,SQLJ还提供了检索迭代程序列的值得存取方法。下列代码在一个循环中打印出雇员姓名,职务和雇用日期。

while (empIterator.next()) {
System.out.println("Name: " + empIterator.Ename());
System.out.println("Job: " + empIterator.Job());
System.out.println("Hire Date:" +
empIterator.HireDate().toString());
}
empIterator.close();

关闭迭代程序对象∶<0}
empIterator.close();

   程序段一把从第2步到第5步联结起来演示了使用了命名迭代程序和empSalary参数的listEmployees ()方法。位置迭代程序与命名迭代程序相反,位置迭代程序只是指定了列的数目和种类,而不是它们的名称。列数据可以只通过位置访问,通过传统的FETCH... INTO语法。除了使用FETCH语句之外,还需要使用位置迭代程序方法endFetch ()来检测结束条件从而从循环中跳出。但是必须在访问所需要取得的数据之间检查条件。

   下面是相同的五个步骤,演示如何使用位置迭代程序:

   声明迭代程序类

    #sql iterator EmpIteratorClass(String, String, Timestamp);

   从迭代程序类中声明迭代程序对象。还必须声明从迭代程序对象中取得的数据所必需的主变量。


EmpIteratorClass empIterator;
String name = null;
String job = null;
Timestamp hireDate = null;

   使用SQL SELECT语句加入迭代程序对象


int salary = 1500;
#sql empIterator = {
select Ename, Job, HireDate
from Emp
where Sal > :salary
};

   把数据从迭代程序对象中读入主机变量


while (true) {
#sql { FETCH :empIterator INTO :name, :job, :hireDate };
if (empIterator.endFetch()) {
break;
}

System.out.println("Name: " + name);
System.out.println("Job: " + job);
System.out.println("Hire Date:" + hireDate().toString());
}


   关闭迭代程序对象

    empIterator.close();

   把从第2步到第5步联结起来演示了使用了位置迭代程序和empSalary参数的listEmployees ()方法。可见,位置迭代程序对象所使用的语法很像PL/SQL游标的语法。命名迭代程序和位置迭代程序两者都执行基本相同的功能它们都保存SQL查询的结果,有可能还是很多行数据至于到底使用哪一种迭代程序则要看情况或是根据自己的偏爱;从性能角度上来看呢,它们产生的结果都是一样的。

   可执行语句

   可执行的SQLJ语句在一对大括号内包含了静态的SQL操作。有两种可能的可执行语句,由SQL是否回来一个值来决定。下面是一个不返回值的嵌入式SQL语句的例子;它在Emp表的Ename列和Sal列上创建一个复合索引


#sql { create index EMP_ENAME_SAL on Emp(Ename, Sal) };

   如果一个嵌入式SQL语句返回值的话,你需要使用一个主机变量来指定结果应该放在什么地方。在本例子中,调用PL/SQL函数getSalary返回雇员号Empno7900的雇员的工资。你可以使用VALUES或者SET运算符来调用函数;也就是说,


int salary;
int empNo = 7900;
#sql salary = { VALUES getSalary(:empNo} };
or
#sql { SET :salary = getSalary(:empNo) };

   主机表达式

   在上面的例子中,我们可以看到,主机变量允许SQLJ程序在数据库和Java程序之间交换信息。它们是任何在Java程序中声明的变量。主机变量被嵌入到SQLJ语句里,称作主机表达式。主机表达式把主机变量绑定在SQLJ可执行语句上,它们也可能包括Java数组元素,对象属性或者Java函数。SQLJ负责在SQLJava环境之间来回移动数据。所有的标准JDBC类型-BooleanbyteshortintStringbyte []doublefloatjava.sql.Date等等。?都是SQLJ中有效的主机表达式。此外,OracleSQLJ翻译器支持使用Oracle数据库类型,例如ROWIDCLOBBLOBObject以及REF类型。在本文中,我讨论了编写实际的SQLJ代码所必需用到的SQLJ对象类型:连接上下文,命名和位置迭代程序,可执行语句和主机表达式。在以后的文章里,我想编写一个服务器SQLJ程序,编译它,然后把它配置进Oracle JServer并把它PL/SQL对应的程序进行性能上的比较。

代码段1
public static void listEmployees(String empSalary)
throws SQLException {
EmpIteratorClass empIterator;
Integer salary = new Integer(empSalary);
try {
#sql empIterator = {
select Ename, Job, HireDate
from Emp
where Sal > :salary
};
while (empIterator.next()) {
System.out.println("Name: " + empIterator.Ename());
System.out.println("Job: " + empIterator.Job());
System.out.println("Hire Date:" +
empIterator.HireDate().toString());
}
empIterator.close();
} catch (SQLException e) {
System.err.println("SQLException" + e);
System.exit(1);
}
}
代码段2
public static void listEmployees(String empSalary)
throws SQLException {
EmpIteratorClass empIterator;
Integer salary = new Integer(empSalary);
/*
主机变量 */
String name = null;
String job = null;
Timestamp hireDate = null;
try {
#sql empIterator = {
select Ename, Job, HireDate
from Emp
where Sal > :salary
};
while (true) {
#sql { FETCH :empIterator INTO :name, :job, :hireDate };
if (empIterator.endFetch()) {
break;
}

System.out.println("Name: " + name);
System.out.println("Job: " + job);
System.out.println("Hire Date:" + hireDate().toString());
}
empIterator.close();
} catch (SQLException e) {
System.err.println("SQLException" + e);
System.exit(1);
}
}

 
原创粉丝点击