由于项目需要,需要在存储过程中调用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