持久数据库更改通知

bas*_*sin 5 java oracle jdbc

我需要监视 oracle 表的更改,并且我正在尝试在Database Change Notifications和之间进行选择Advanced Queuing

我不明白数据库 JDBC 开发人员指南getDatabaseChangeRegistration javadoc中的某些要点

如果我使用该标志注册数据库更改注册 (DCR) NTF_QOS_RELIABLE,我希望通知在我的 jdbc 应用程序关闭时持续存在。但是,我没有看到在我的应用程序重新启动后恢复现有 DCR 的方法:根据 javadoc,getDatabaseChangeRegistration()仅适用于 PLSQL 侦听器。当我的应用程序终止时,jdbc DCR 似乎会被销毁,我什至不需要取消注册它们。

当我的程序重新启动后,我有时会收到带有先前注册 ID 的通知。不必stmt.setDatabaseChangeRegistration()每次启动应用程序时都调用。

我从来没有收到过在我的应用程序关闭时发生的更改,这是最大的问题。那做什么呢NTF_QOS_RELIABLE

package org.foo;

import static oracle.jdbc.OracleConnection.*;

import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.Locale;
import java.util.Properties;

import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleStatement;
import oracle.jdbc.dcn.DatabaseChangeEvent;
import oracle.jdbc.dcn.DatabaseChangeListener;
import oracle.jdbc.dcn.DatabaseChangeRegistration;

// CHECKSTYLE.OFF: Name|Reg
public final class TestDbListener {

    private TestDbListener() {}

    public static void main(final String[] args) throws Exception {
        Locale.setDefault(Locale.US);

        Class.forName("oracle.jdbc.OracleDriver");
        final OracleConnection conn =
                (OracleConnection) DriverManager.getConnection(
                        "jdbc:oracle:thin:@192.168.56.150:1521:xe", "scott", "tiger");

        final Properties props = new Properties();
        props.setProperty(NTF_QOS_RELIABLE, "true");

        final DatabaseChangeRegistration dcr = conn.registerDatabaseChangeNotification(props);
        final DCNListener list = new DCNListener();
        dcr.addListener(list);

        if (true) {

            // now you need to add whatever tables you want to monitor
            final OracleStatement stmt = (OracleStatement) conn.createStatement();
            // associate the statement with the registration:
            stmt.setDatabaseChangeRegistration(dcr);

            final String sql = "select * from a where 1=2";
            final ResultSet rs = stmt.executeQuery(sql);

        }

        final String[] tableNames = dcr.getTables();
        for (int i = 0; i < tableNames.length; i++) {
            System.out.println(tableNames[i] + " has been registered.");
        }

        Thread.sleep(1000000);

        // rs.close();

    }

}

class DCNListener implements DatabaseChangeListener {

    @Override
    public void onDatabaseChangeNotification(final DatabaseChangeEvent event) {
        System.out.println("onDatabaseChangeNotification: " + event);
    }
}
Run Code Online (Sandbox Code Playgroud)

SQL:

-- sysdba: 
-- grant change notification to scott;

-- scott:
create table a ( a int );

insert into a values ( 1 );
commit;
Run Code Online (Sandbox Code Playgroud)

Jea*_*ene 1

NTF_QOS_RELIABLE可用于控制服务器上使用哪种类型的队列来处理通知。请参阅此文档: https://docs.oracle.com/cd/B28359_01/appdev.111/b28395/oci10new.htm#CHDFCCJE

关于NTF_QOS_RELIABLE

即使在节点发生故障后,Oracle RAC 的幸存实例也可用于发送和检索连续查询通知消息,因为与此注册相关的失效会永久排队到数据库中。如果为 FALSE,则失效将被排入快速内存队列中。请注意,此选项描述的是通知的持久性,而不是注册的持久性。默认情况下,注册会自动持久。

如果您的应用程序死机,则假设在重新启动期间您将从要监视的表中获取最新数据。因此,不需要在崩溃和重新启动之间发送的通知。

请注意,重新启动时需要调用conn.registerDatabaseChangeNotification重新启动驱动程序的侦听器。