现在的位置: 首页 > 综合 > 正文

JAVA SOURCE (1)

2013年05月17日 ⁄ 综合 ⁄ 共 4888字 ⁄ 字号 评论关闭
文章目录

用Java开发Oracle存储过程

Java 2010-02-08 03:51:04 阅读375 评论0   字号: 订阅

Java开发Oracle存储过程

作者:Michael Klaene

原文:http://www.developer.com/db/article.php/3337411

译者:玄机逸士

 

Oracle 8i开始,Oracle数据库就全面引入了实用的Java虚拟机 – Oracle JVMOracleJava之间的这种紧密关系,使得一个非常重要的技术,出现在Oracle开发人员面前:Java存储过程。通过Java存储过程,开发人员在创建数据库应用的时候,就可以充分利用Java提供的各种优势。本文将针对这个越来越受欢迎的技术进行讨论。其目标读者是,初懂OracleJava开发人员和略知JavaOracle PL/SQL开发人员。在强调Java存储过程的好处之后,我将示例说明在应用开发中,如何使用它们。

 

Java存储过程的好处

在很多情况下使用Java存储过程是很有意义的。鉴于Java当前受欢迎的程度,这种情况是完全可能的,即越来越多的开发人员对于Java的熟练程度要好于PL/SQLJava存储过程的出现,使得Java的开发人员可以用自己喜欢的语言来开发存储过程。对于有经验的PL/SQL开发人员,则可以利用Java语言的各种优点,来扩展数据库应用的功能。同时,Java使得编写独立于数据库的代码成为可能。更有意思的是,它允许你重用你已经存在的代码,从而大幅度地提高开发效率。

 

正如你将看到的, PL/SQLJava 可以在同一个应用中和谐共处,因此,大可不必非此即彼地选择其中之一。 PL/SQL是一种针对Oracle数据库,经过高度优化的、优秀的过程语言,Java应用在Oracle数据库中运行也具有很好的扩展性。除此之外,通过OracleJVM来执行Java程序,可以充分利用高效的内存回收技术和线程管理方面的能力。

 

Java存储过程,Step by Step

简单地说,Java存储过程就是Java类,以schema对象的形式存储,通过调用规范(call specifications)OracleSQLPL/SQL可以对其访问。我们将看到,调用规范就是一些简单的PL/SQL声明,这些声明包装(wrap)’了存储在数据库中的Java方法。开发Java存储过程,有四个必须的步骤。下面我们逐一来看看这些步骤。

 

#1. 编写Java

第一步的妙处就是,它基本上和Oracle数据库没有什么关系。你只是简单地用你最喜欢的IDE,比如OracleJdeveloper,去开发一些Java类。如果想被用作存储过程,Java方法必须是publicstatic的。

 

在移入Oracle数据库之前,你可以自由地编写、编译甚至对Java代码进行单元测试。事实上,对于通常的应用,这是一个很好的方式,因为这可以充分利用IDE的特性,诸如调试和代码生成。如果你想用OracleJVM来编译Java代码,后面将要说到的loadjava这个工具,将为你做这些工作。

 

下面的代码列出了一个简单的Java - EmpManager。它包只含了一个简单的,用于向数据库插入一个emp(员工)记录的方法。

 

import java.sql.*;

import oracle.jdbc.*;

 

public class EmpManager {

 

  //Add an employee to the database.

  public static void addEmp(int emp_id, String emp_f_name,

      String emp_l_name,float emp_salary, int dept_id) {

 

      System.out.println("Creating new employee...");

 

      try {

         Connection conn =

            DriverManager.getConnection("jdbc:default:connection:");

 

         String sql =

            "INSERT INTO emp " +

            "(emp_id,emp_f_name,emp_l_name,emp_salary,dept_id) " +

            "VALUES(?,?,?,?,?)";

         PreparedStatement pstmt = conn.prepareStatement(sql);

         pstmt.setInt(1,emp_id);

         pstmt.setString(2,emp_f_name);

         pstmt.setString(3,emp_l_name);

         pstmt.setFloat(4,emp_salary);

         pstmt.setInt(5,dept_id);

         pstmt.executeUpdate();

         pstmt.close();

         }

      catch(SQLException e) {

         System.err.println("ERROR! Adding Employee: "

           + e.getMessage());

         }

  }

}

 

到目前为止一切如常。在这个方法中,数据库链接URL"jdbc:default:connection:"。在写要在Oracle数据库中运行的Java代码时,可以利用一个特殊的服务器端的JDBC驱动程序。这个驱动程序使用用户缺省的链接,并提供对数据库的最快访问速度。

 

#2. 加载Java

我们的Java类将要编程一个真正的schema对象,所以必须将它移入数据库。为此,Oracle提供了一个命令行工具 – loadjava。这个loadjava工具提供了一个SQL CREATE JAVA等语句必要的接口,并且也可以用于将Java相关的文件加载到数据库中。

 

由于现在还没有编译EmpManager.java,我们也可以让loadjava在加载的过程中顺便做完编译工作,这个可以通过打开 –resolve开关来做到。

 

$ loadjava –u scott/tiger –v –resolve EmpManager.java

–resolve 开关外, -v 将指示loadjava输出详细的(verbose)反馈, -u 用于指定数据库用户和密码。因为我们让loadjava编译源文件,因此源文件和类文件都将是SCOTT schema的成员。

 

我们可以通过一个对USER_OBJECTS的查询来验证编译和加载的状态,如果正确,那么状态将是’VALID’的。

 

SELECT object_name, object_type, status

FROM user_objects WHERE object_type LIKE ‘JAVA%’;

 

object_name object_type status

 

EmpManager JAVA CLASS  VALID

EmpManager JAVA SOURCE VALID

 

反之,如果编译失败,可以在视图USER_ERRORS中看到具体的错误。

 

如果选择用IDE编译,只需要简单将编译后的class文件加载即可,源文件可以保存在版本控制工具的文件系统中。Loadjava工具接受后缀为.sqlj (sqlj 源文件).properties.ser.jar.zip等文件。当后缀为.jar zip的文件时,Oracle将自动解压,并将各成员存储成单个的schema对象。

 

在继续讨论之前,加载过程中有一个至关重要的组件值得一提:Oracle JVM resolver。典型地,一个JVMclasspath来定位Java类,以便被其他程序使用。在数据库中加载Java时,resolver来完成这样的任务。

 

可以简单地认为resolver就是Oracle版本的classpathOracle将核心Java类存储与PUBLIC schema中。PUBLIC,就像你自己的schema一样,将被自动地引入缺省的resolver中。不过,如果需要引用另外一个schema中的类,那就必须提供你自己的’resolver规则(spec)’,这个可以通过加上-resolver开关来做到。比如,loadjava –u scott/tiger@test –resolve –resolver “((* SCOTT) (* PUBLIC) (* ADMIN))” ,指明了,在决定class依赖关系时,SCOTT schemaPUBLIC ADMIN3schema将被搜索。

 

#3. 发布(publish)Java

3步是发布Java类。Java类必须发布,以便可以直接从SQL或者PL/SQL直接访问。通过为其创建、编译一个调用规则来发布一个Java类。调用规则,通常被称为call spec或者PL/SQL包装器(wrapper),它将Java方法的参数、返回值类型映射成Oracle SQL的数据类型。下面给出的是addEmp方法的调用规则:

 

CREATE OR REPLACE PROCEDURE add_emp (emp_id NUMBER,emp_f_name VARCHAR2,

  emp_l_name VARCHAR2, emp_salary NUMBER, dept_id NUMBER)

  AS LANGUAGE JAVA

  NAME 'EmpManager.addEmp(int, java.lang.String, java.lang.String,

                          float, int)';

/

 

add_emp过程为Java EmpManager.addEmp方法提供了一个SQL接口。Java方法,如果有相关包名,则必须使用包含包名的全名,并且,在开发一个调用对则时,Java对象如String也必须使用全名。

 

作为一般性的规律,一个Java方法如果没有返回值,则被封装成过程,反之,则被封装成函数。现在,在EmpManager中,我们考虑加入第2Java方法,用于查询一个指定部门的员工人数:

 

// 查询一个指定部门的员工人数

public static int getEmpCountByDept(int dept_id) {

 

  Connection conn =

      DriverManager.getConnection("jdbc:default:connection:");

 

  String sql = "SELECT COUNT(1) FROM emp WHERE dept_id = ?";

  int cnt = 0;

 

  //Code here to add ResultSet value to cnt, trap SQLException, etc.

 

  return cnt;

}

 

它的调用规则指定其返回类型为NUMBER

 

CREATE OR REPLACE FUNCTION get_emp_count_by_dept (dept_id NUMBER)

  RETURN NUMBER AS LANGUAGE JAVA

  NAME 'EmpManager.getEmpCountByDept(int) return int';

/

 

缺省地,就像标准的PL/SQL 过程一样,这些代码(译注:指上面的调用规则)只要有INVOKER权限就可以运行他们,换言之,当前用户有权执行它们。通过增加关键字AUTHID DEFINER,可以让其他用户以创建者的身份来执行它们。

 

一旦执行,调用规则,则将其他文件作为SCOTT schema的成员加入数据库。

 

#4. 调用过程

我们已经开发、装载并发布了Java类。最后一步就是执行他们。缺省地,Java的输出被写入跟踪文件(trace files)DBMS_JAVA

抱歉!评论已关闭.