以下の内容はhttps://kagamihoge.hatenablog.com/entry/20120714/1342261047より取得しました。


Oracleのデータベース変更通知

2025/3/21 追記

  • Oracle Database 23ai Free Release 23.0.0.0.0

どのバージョンからかは不明だが、期待通りの動作をするにはOracleConnection.DCN_CLIENT_INIT_CONNECTIONプロパティをtrueにする必要があるようだ。

    Properties prop = new Properties();
    prop.setProperty(OracleConnection.DCN_CLIENT_INIT_CONNECTION, "true");

以下はリファレンス該当部分から引用。

https://docs.oracle.com/en/database/oracle/oracle-database/23/jjdbc/continuos-query-notification.html#GUID-02906A67-AB25-4026-87AB-F10E780C928D

31.2 Overview of Client Initiated Continuous Query Notification
Starting from Oracle Database Release 19c, the JDBC Thin driver supports the Client Initiated Continuous Query Notification feature. In this case, the client application initiates a connection to the database server for receiving notifications.

A client application first initiates a new database connection before creating a Continuous Query Notification registration. When the application creates a registration, the JDBC driver internally starts a new thread and creates a new connection with the database server. The database server then uses this new connection to send change notifications to the client.

By default, this feature is disabled for an on-premise database. You must set the OracleConnection.DCN_CLIENT_INIT_CONNECTION to true for enabling this feature.

DCN_CLIENT_INIT_CONNECTION - Specifies Client Initiated Continuous Query Notification, where the client application initiates a database connection, which the server uses to send change notifications to the client.

見た限りでは、クライアント側からCQNの接続を開始する、という設定のようだ。なのでクライアント側アプリケーションを終了するとCQNも停止、具体的にはUSER_CHANGE_NOTIFICATION_REGSテーブルから行が削除される、という動作になる。11gの頃と現在とでは色々変わったという事なんだろうけど、どの辺が変わったのかまでは調べていない。

参考URL

2025/3/21 追記 ここまで

JDBCドライバでは、SQL問合せをデータベースに登録して、次のイベントの発生時に通知を受け取ることができます。

問合せに関連付けられたオブジェクトに対するDMLまたはDDL変更。

結果セットに影響を与えるDMLまたはDDL変更。

Oracle Database JDBC開発者ガイド 11gリリース2(11.2)- 26 データベース変更通知 より抜粋

とまぁ、面白そうな機能があるのでとりあえず使ってみる。

環境

ソースコードなど

public class OracleNotify {

    public static void main(String[] args) throws Exception {
        Connection connection = DriverManager.getConnection(
                "jdbc:oracle:thin:@localhost:1521:XE", "xxxx", "xxxx");
        
        Properties prop = new Properties();
        prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS,"true");
        prop.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION,"true");
        OracleConnection c = (OracleConnection)connection;
        DatabaseChangeRegistration dcr = c.registerDatabaseChangeNotification(prop);

        dcr.addListener(new DatabaseChangeListener() {
            @Override
            public void onDatabaseChangeNotification(DatabaseChangeEvent arg0) {
                System.out.println(arg0);
            }
        });
        
        Statement stmt = c.createStatement();
        ((OracleStatement)stmt).setDatabaseChangeRegistration(dcr);
        
        ResultSet rs = stmt.executeQuery("select belongid, employeeid from belongto where belongid=43");
        while (rs.next())
        {}
        String[] tableNames = dcr.getTables();
        for(int i=0;i<tableNames.length;i++)
            System.out.println(tableNames[i]+" is part of the registration.");

        Thread.sleep(40000);
        stmt.close();
        c.unregisterDatabaseChangeNotification(dcr);
        connection.close();
    }
}

とりあえず動けばいいって感じのコードで、色々なところを手抜き工事しているのはかんべんしてください。細かいところはjavadoc参照ということで。OracleConnection (Oracle Database JDBC Java API Reference)

このコードを動かすと何がおきるか。(40000msのスリープしてる間に)SQL Developer等を用いてbelongtoテーブルのbelongid=43行をUPDATEすると以下のような出力がされる。


Connection information : local=localhost/127.0.0.1:47634, remote=localhost/127.0.0.1:2643
Registration ID : 9
Notification version : 1
Event type : QUERYCHANGE
Database name : XE
Query Change Description (length=1)
query ID=3, query change event type=QUERYCHANGE
Table Change Description (length=1): operation=[UPDATE], tableName=KAGAMIHOGE.BELONGTO, objectNumber=20051
Row Change Description (length=1):
ROW: operation=UPDATE, ROWID=AAAE5TAAEAAAAFNAAI

Oracle側から、変更通知対象テーブルの行(ここではselect belongid, employeeid from belongto where belongid=43のこと)に変更があったことがROWID等の情報とともにイベント通知されてるのが分かります。




以上の内容はhttps://kagamihoge.hatenablog.com/entry/20120714/1342261047より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14