天天看点

java存储过程开发总结

       Java Stored Procedures(简称JSP,此JSP非彼JSP,哈哈哈),即JAVA存储过程,是通过Oracle数据库中的DML、package等调用JAVA程序,从而实现Oracle数据库与JAVA集成。由于工作需要,要通过Oracle数据库调用JAVA程序,与ActiveMQ集成实现消息发送,网上大多数例子都是通过Oracle数据库调用java程序实现最基本的Hello程序,更深入的研究也比较少。经过长时间的纠结,最终实现了消息发送,现总结如下,供需要的童鞋们参考。本文基于Oracle Database11g Release2。

1、主要参考资料

最基本参考资料就是Oracle官方文档:Oracle Database Java Developer's Guide

其他的就百度吧。

2、开发步骤

(1)编写JAVA程序

跟平常JAVA开发一样,该怎么编写就怎么编写,但要注意,通过数据库调用的方法必须为static的,下面为发送消息的JAVA代码框架:

package com.test;

/**
 * 
 *
 */
public class JspSendMsg {
	
	public static String sendMsg(String str){
		//发送消息成功标志
		String b = "Y"; 
		System.out.println("发送消息开始。。。。");
		try {
			//实现消息发送,此处略
			//......
			
			System.out.println("发送消息成功!");
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("发送消息失败!");
			b = "N";
			e.printStackTrace();
		}
		return b;
	}
	
}
           

(2)加载JAVA类到数据库中

有两种方式:

a、通过pl/sql新建Java source,把第(1)步中java代码直接copy进来,编译即可;

create or replace and compile java source named JspSendMsg as
package com.test;

/**
 * 
 *
 */
public class JspSendMsg {
  
  public static String sendMsg(String str){
    //发送消息成功标志
    String b = "Y"; 
    System.out.println("发送消息开始。。。。");
    try {
      //实现消息发送,此处略
      //......
      
      System.out.println("发送消息成功!");
    } catch (Exception e) {
      // TODO: handle exception
      System.out.println("发送消息失败!");
  		b = "N";
			e.printStackTrace();
		}
		return b;
	}
	
}
           

b、利用loadjava工具

loadjava工具是oracle数据库提供的一个命令行工具,它可加载java源文件、java class类、jar包、资源文件到数据库中,根据需要自行选择。

--加载java源文件

loadjava -u scott/[email protected] -v -r g:\com\test\JspSendMsg.java

其中,

  u---参数表示连接数据库的用户

  v---加载时输出详细日志

  r---加载时利用oracle jvm进行解析,生成class文件

--加载java class文件

loadjava -u scott/[email protected] -v g:\com\test\JspSendMsg.class

注意,加载已编译的class文件时需注意编译java类的JDK版本与Oracle jvm版本必须一致,否则可能会出问题,11g对应的JDK为1.5,10g为1.4。

(3)发布java类

发布java需在数据库中进行,通过package调用JspSendMsg类,发布如下:

package头:

  function sendMsg(msg varchar2) return VARCHAR2;

package体:

  function sendMsg(msg varchar2) return VARCHAR2 as

  LANGUAGE JAVA NAME 'com.test.JspSendMsg.sendMsg(java.lang.String) return java.lang.String';  

至此,编码部分基本完毕,在测试前还有些事情需要做。

(4)加载jar包

由于是实现消息发送,需要把activemq-all-5.2.0.jar加载进数据中。通过loadjava工具加载jar包时,由于待加载jar包可能依赖其他第三方jar包,需提供-genmissing参数,否则有些class文件无法编译。如有多个jar包,可一起加载。loadjava加载jar包时会解压jar文件,把jar中每个class进行分别加载。

命令形式:

loadjava -u scott/[email protected] -genmissing -r -v -f -fileout active.txt activemq-all-5.2.0.jar

其中,

  genmissing---表示如果该jar包里依赖其他jar包,而其他jar包数据库中并不存在,此时数据库会忽略,并产生该class文件,具体可参见loadjava工具说明。

  f---强制加载

  fileout---输出日志到文件active.txt中

(5)加载资源文件ia.properties

为编译维护,把消息服务器IP地址、端口、消息队列名称配置在配置文件中,需加载到数据库中,用户java程序解析该配置文件。

命令形式:

loadjava -user scott/[email protected] -v ia.properties

注意,ia.properties前不能加其他路径,需在当前路径下执行,否则java程序找不到该配置文件。

(6)授权

通过Oracle数据库调用java程序时,需要进行授权,授权时需要DBA权限用户。本文主要用到以下两种:

--使用java类加载器时需进行此授权,本例中需要读取配置文件,因此需要此授权

call dbms_java.grant_permission( 'scott', 'SYS:java.lang.RuntimePermission', 'getClassLoader', '')

--访问网络时需要进行此授权

call dbms_java.grant_permission( 'scott', 'SYS:java.net.SocketPermission', '消息服务器IP地址:消息port', 'connect,resolve')

(7)至此,可以进行消息发送测试了。本例实现了简单的消息发送。

3、设置重定向

通过Oracle数据库调用java程序,不太好查看java程序里的输出信息,pl/sql提供了设置重定向功能,可将java程序里System.out等输出信息进行重定向,在pl/sql命令行窗口执行:

SET SERVEROUTPUT ON; 

CALL dbms_java.set_output(2000);

然后调用程序时即可看到输出信息到命令行窗口。

4、最后提供一些有用的脚本。

--删除单个class

dropjava -user scott/[email protected] -r -v -f com/test/JspSendMsg

--执行loadjava后查询一下状态

SELECT uo.created ,uo.object_name, uo.object_type, dbms_java.longname(uo.object_name),uo.status,uo.*

  FROM user_objects uo WHERE 1=1

  --and object_type like 'JAVA%'

  order by uo.created desc;

--生成批量删除java类命令

select 'dropjava -u scott/[email protected] -r -v -f '||dbms_java.longname(uo.object_name) FROM user_objects uo

WHERE object_type='JAVA CLASS';

--java数据库对象原名称与别名对应关系

select * from javasnm js;

--编译java源文件错误信息视图

select * from USER_ERRORS ue where ue.type like 'JAVA%';

--数据库中policy视图,用户查看当前用户被授予的权限

select * from USER_JAVA_POLICY;

--权限操作

--授权

见本文前面

--删除权限:需先收回再删除

call dbms_java.revoke_permission('scott', 'SYS:java.lang.RuntimePermission', 'getClassLoader', '*');

call dbms_java.delete_permission(key => 153); --153对应表user_java_policy.KIND列值