由于项目需要,需要在存储过程中调用java类,特在此进行总结。
环境: centos764bit jdk7 oracle10g64bit
先编写java代码 Demo.java,代码如下:
package com.longshine.procedure; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Properties; public class Demo { public static String url = "url not set"; public static String userName = "userName not set"; public static String pwd = "pwd not set"; public static String query(String arg){ String result = ""; init(); result = "arg is "+arg +" & url:" + url; return result; } public static void main(String[] args){ init(); System.out.println("arg is "+args[0] +" & url:" + url); } public static void init(){ Properties props = new Properties(); try { props.load(new FileInputStream("/home/oracle/javademo/procedure.properties")); url = props.getProperty("url","url not set"); userName = props.getProperty("userName","userName not set"); pwd = props.getProperty("pwd","pwd not set"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static String helloWordFunction(){ return "helloMoto"; } }
java代码存放于 /home/oracle/javademo/Demo.java
代码中用到的配置文件内容如下:
url=http://192.168.1.137 userName=aaa pwd=bbb
配置文件存放于 /home/oracle/javademo/procedure.properties
我们的目的是通过JDBC调用存储过程或自定义函数来调用Demo.java的query方法,并取得返回值。
我们操作JDBC和存储过程使用的oracle用户为scott 密码为tiger
在linux命令行下执行
loadjava -u scott/tiger@orcl -v -resolve /home/oracle/javademo/Demo.java
这个命令可以在scott的用户下,载入java,供后续创建存储过程使用。
检查java是否load成功,在sqlplus中执行
SELECT a.OBJECT_NAME, a.OBJECT_TYPE,a.status FROM user_objects a WHERE a.OBJECT_NAME LIKE ‘%Demo%’;
创建自定义函数,在sqlplus中,使用scott用户执行
CREATE OR REPLACE FUNCTION fib (args String) RETURN VARCHAR2 AS LANGUAGE JAVA NAME 'Demo.query(java.lang.String) return String';
由于我们要读取配置文件。所以需要用SYS用户对scott用户赋予读取配置文件的读文件权限。
使用SYS用户在sqlplus里执行
call dbms_java.grant_permission( ‘SCOTT’, ‘SYS:java.io.FilePermission’, ‘/home/oracle/javademo/procedure.properties’, ‘read’ );
如果我们想修改java类。那么可以在LINUX命令行中执行
dropjava -u scott -v Demo
然后修改java类,重新load 重建自定义函数即可。
下面是测试代码 TestProcedure.java:
package com.longshine.procedure; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Types; public class TestProcedure { public static void main(String[] args) { new TestProcedure().testOracle(); } /** * 一个非常标准的连接Oracle数据库的示例代码 */ public void testOracle() { Connection con = null;// 创建一个数据库连接 PreparedStatement pre = null;// 创建预编译语句对象,一般都是用这个而不用Statement ResultSet result = null;// 创建一个结果集对象 CallableStatement stmt = null; try { Class.forName("oracle.jdbc.driver.OracleDriver");// 加载Oracle驱动程序 System.out.println("开始尝试连接数据库!"); String url = "jdbc:oracle:" + "thin:@192.168.1.137:1521:orcl";// 127.0.0.1是本机地址,XE是精简版Oracle的默认数据库名 String user = "scott";// 用户名,系统默认的账户名 String password = "tiger";// 你安装时选设置的密码 con = DriverManager.getConnection(url, user, password);// 获取连接 System.out.println("连接成功!"); String sql = "{? = call fib(?)}"; stmt = con.prepareCall(sql); stmt.setString(2, "asss"); stmt.registerOutParameter(1, Types.LONGNVARCHAR); stmt.execute(); String resultString = stmt.getNString(1); System.out.println(resultString); } catch (Exception e) { e.printStackTrace(); } finally { try { if(stmt != null){ stmt.close(); } if (result != null) result.close(); if (pre != null) pre.close(); if (con != null) con.close(); System.out.println("数据库连接已关闭!"); } catch (Exception e) { e.printStackTrace(); } } } }
执行main方法之后 控制台输出结果为
开始尝试连接数据库!
连接成功!
arg is asss & url:http://192.168.1.137
数据库连接已关闭!
至此 我们的目标已经达成。
调用无返回值的java方法时可以使用存储过程,调用有返回值的java方法时可以调用自定义函数,期间参考的英文网址为:
http://docs.oracle.com/cd/B28359_01/java.111/b31225/chthree.htm#CBBEJGIH