天天看點

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列值