美文网首页Oracle数据库管理之道我爱编程
Oracle实现监听表变化并利用Java调用WebService

Oracle实现监听表变化并利用Java调用WebService

作者: morningstarwang | 来源:发表于2017-08-31 14:41 被阅读473次

    前段时间接到了这样的需求。有两套网络隔绝的Oracle数据库(假设为数据库A和数据库B)(A可以连接互联网,B处于封闭局域网内不可连接互联网),两者进行数据交换是通过某设备将A的表的变化通过insert插入到B的对应表中,同样地,B在进行数据处理后要通过某设备将B的表的变化通过insert插入到A的对应表中。详细流程如下图所示。

    从整个流程中我们可以找到该项目的技术要点在于Oracle调用WebService取回JSON数据并进行解析。我们很容易的想到要利用Oracle触发器+存储过程来完成这一任务。

    在查阅相关资料后,我们找到了实现调用WebService的三种途径,它们分为两大思路。第一个思路是通过Oracle自身的存储过程调用,这需要引入UTL_DBWS或者UTL_HTTP进行调用。笔者曾经尝试了这两种方式,发现:这两种方式要求严格的SOAP报文格式,普适性并不够强。由于笔者所调用WebService的环境较为特殊,不能经常调用进行测试。因此,笔者抛弃了这两种普适性不强的策略。有兴趣的读者可以自行Google以上两个关键字,这里不再赘述。而第二个思路是通过Oracle调用Java程序进行WebService,因为Java环境下存在AXIS这样的第三方库,我们可以方便的获取WebService数据。这种思路的难点便变成了向Oracle中导入相关JAR包。

    首先介绍一下本次项目的环境:

    操作系统:RHEL 6.4 (Linux)

    Oracle数据库:Oracle 11g

    Oracle JVM版本:jdk_1_5_17

    1. 确定Oracle JVM版本

    确定Oracle JVM版本对于Java项目的编译至关重要,由于不同Oracle版本的数据库自带JVM版本不同(且比较低),因此,我们需要进行版本的确认。方法如下:

    在终端依次输入以下命令:

    ①切换至Oracle用户

    su oracle

    [密码]

    ②初始化Oracle环境

    . oraenv

    [实例名]

    ③切换至$ORACLE_HOME目录

    cd $ORALCE_HOME/jdk/bin

    ④调用java -version命令

    ./java -version

    至此我们可以确定JVM的版本,然后在后续编程中需要把eclipse的编译器和Library版本全部改为刚才查到的版本,小版本号也要确保一致。(jdk需要从Oracle官网下载指定版本)

    2. 编写Java程序

    我们这里采用的是AXIS2方案,首先从WSDL文件生成相关的WebService类,然后新建一个Main类,声明一个main方法,在这里我只列举主要代码,如果各位读者需要进一步的帮助,请联系我的简信或者email我。

    public  static void main(String arg1, String arg2){

        IDataQueryWSPortTypeProxy proxy = new IDataQueryWSPortTypeProxy();

        proxy.setEndpoint("http://XX.XX.XX.XX:XXXX/dataquery");

        JSONObject jo= new JSONObject();

        JSONArray ja = new JSONArray();

        ja.add(arg1);

        jo.put("aaaa", "123");

        jo.put("bbbb",ja);

        String senderID = "0523";

        String serviceID = "2356";

        String [] endUser = null; 

        String dataObjectCode = null;

        String [] requiredItems = {"cccc","dddd"};

        String condition = jo.toString();

        String infoCodeMode = null;

        String res = proxy.query(senderID, serviceID, endUser, dataObjectCode, condition, requiredItems, infoCodeMode, arg1, arg2);

    }

    注意,main函数的参数根据大家不同的需求最好更改为需要查询的条件参数,这样的函数在eclipse是无法运行的,但是在Oracle下可以运行,在大家调试Java程序时可以先使用String[] args参数进行,最后在打包生成JAR包前改为笔者这样的参数格式,方便Oracle调用。

    由于笔者这里的搭建环境特殊,使用了eclipse进行Java的编写,因此笔者这里使用了Fatjar插件进行打包,可以轻松的将全部JAR引用包打在一起。打包成JAR包的过程这里不再赘述。

    2. 配置Oracle用户权限

    考虑到Oracle数据库安全,在对数据库B进行操作时,要独立使用一个用户进行管理。现在要求该用户权限至少等同于默认SCOTT用户权限,并且还要附加以下权限。先以sysdba身份登录sqlplus然后执行以下命令授权(用户名必须为英文大写字母)(请将SCOTT替换为你所使用的用户):

    grant CREATE PUBLIC SYNONYM to SCOTT;

    call dbms_java.grant_permission('SCOTT','SYS:java.lang.RuntimePermission', 'shutdownHooks', '' );

    call dbms_java.grant_permission('SCOTT','SYS:java.util.logging.LoggingPermission', 'control', '' );

    call dbms_java.grant_permission('SCOTT','SYS:java.util.PropertyPermission','http.proxySet','write');

    call dbms_java.grant_permission('SCOTT','SYS:java.util.PropertyPermission','http.proxyHost', 'write');

    call dbms_java.grant_permission('SCOTT','SYS:java.util.PropertyPermission','http.proxyPort', 'write');

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

    call dbms_java.grant_permission('SCOTT','SYS:java.net.SocketPermission','*','connect,resolve');

    call dbms_java.grant_permission('SCOTT','SYS:java.util.PropertyPermission','*','read,write');

    call dbms_java.grant_permission('SCOTT','SYS:java.lang.RuntimePermission','setFactory','');

    call dbms_java.grant_permission('SCOTT','SYS:java.lang.RuntimePermission', 'accessClassInPackage.sun.util.calendar','');

    请确认以上语句全部执行成功后在进行后续操作。

    3. 导入编译好的JAR包

    在准备好Oracle环境后,用SSH将打包好的JAR包导入到$ORACLE_HOME/sqlj/lib下,在终端执行以下命令完成导包工作:

    ①切换至lib目录下

    cd $ORACLE_HOME/sqlj/lib

    ②执行导包命令(假设JAR文件名为rpcinvoke.jar,用户名密码分别为SCOTT/tiger)

    loadjava -u SCOTT/tiger -r -v -f -s -grant public -genmissing rpcinvoke.jar >& loadjava.txt

    请耐心等待导包结束,在本文末尾我会提供我调用WebService时引用的全部第三方JAR包,各位读者可以参考使用。导包完成后的日志文件将存储在该目录下的loadjava.txt中,请查看并确定除了oracle jdbc以外其他包导入成功未报异常,这说明WebService的JAVA程序将可以成功运行。

    4. 编写存储过程

    (1)编译JAVA SOURCE

    在PL/SQL或者sqlplus以SCOTT(你所使用的用户)身份登录,执行下面的语句:

    create or replace and compile java source named InvokeIDRPC as package wms;

    import com.edward.wsdldemo.Main;

    public class InvokeIDRPC{

    public static void invokeIDRPC(String arg1, String arg2)

    {

    Main.main(arg1,arg2);

    }

    }

    注意其中的Main.main()方法,代表你所使用的类名.main方法,并且确认你需要传入的参数(这里是arg1和arg2),执行此语句可以将JAVA SOURCE编译到Oracle中。

    (2)编写存储过程

    create or replace procedure InvokeIDRPC_P( arg1 in VARCHAR2,arg2 in VARCHAR2) as language java name 'wms.InvokeIDRPC.invokeIDRPC(java.lang.String,java.lang.String)';

    这里要注意指定参数在存储过程的类型以及在JAVA程序中的类型,对应我的字符串格式就是VARCHAR2和java.lang.String类型。同时也要注意wms指明了刚才java source的package,InvokeIDRPC指明了JAVA SOURCE类的名称,而invokeIDRPC指明了JAVA SOURCE类中方法的名称。

    (3)编写触发器

    create or replace trigger InvokeIDRPC_T

    before insert

    on request_data

    for each row

    begin

    InvokeIDRPC_P(:new.arg1,:new.arg2);

    end;

    这个触发器指明了在request_data表插入数据后取得arg1和arg2字段的值并传入刚才编写好的存储过程中执行。

    5. 总结

    以上是Oracle实现监听表变化并利用Java调用WebService获取数据的完整思路,笔者经过了实际项目测试,爬了好多坑,如果各位读者遇到其他问题可以随时简信或者email联系我,文章相关文件和我的联系方式如下:

    E-mail:wang19970119@outlook.com

    百度云:链接: https://pan.baidu.com/s/1c2m0zgk 密码: zec4

    相关文章

      网友评论

        本文标题:Oracle实现监听表变化并利用Java调用WebService

        本文链接:https://www.haomeiwen.com/subject/kgyadxtx.html