簡體   English   中英

如何使用 Postgres 數據庫在 Java 中獲得異步/事件驅動的 LISTEN/NOTIFY 支持?

[英]How do I get asynchronous / event-driven LISTEN/NOTIFY support in Java using a Postgres database?

據我所知,Java 中用於 LISTEN/NOTIFY 的 JDBC 驅動程序不支持真正的事件驅動通知。 您必須經常輪詢數據庫以查看是否有新通知。

我在 Java 中有哪些選項(可能是 JDBC 之外的其他選項?),如果有的話,可以在沒有輪詢的情況下以真正的事件驅動方式異步獲取通知?

使用 pgjdbc-ng 驅動程序。

http://impossibl.github.io/pgjdbc-ng/

它支持異步通知,無需輪詢。 我已經成功使用了。

https://database-patterns.blogspot.com/2014/04/postgresql-nofify-websocket-spring-mvc.html

Oleg 也有一個很好的示例答案

這是使用 com.impossibl.postgres.api ( pgjdbc-ng-0.6-complete.jar ) 和 JDK 1.8 的異步模式:

import com.impossibl.postgres.api.jdbc.PGConnection;
import com.impossibl.postgres.api.jdbc.PGNotificationListener;
import com.impossibl.postgres.jdbc.PGDataSource;    
import java.sql.Statement;

public static void listenToNotifyMessage(){
    PGDataSource dataSource = new PGDataSource();
    dataSource.setHost("localhost");
    dataSource.setPort(5432);
    dataSource.setDatabase("database_name");
    dataSource.setUser("postgres");
    dataSource.setPassword("password");

    PGNotificationListener listener = (int processId, String channelName, String payload) 
        -> System.out.println("notification = " + payload);

    try (PGConnection connection = (PGConnection) dataSource.getConnection()){
        Statement statement = connection.createStatement();
        statement.execute("LISTEN test");
        statement.close();
        connection.addNotificationListener(listener);
        while (true){ }
    } catch (Exception e) {
        System.err.println(e);
    }
}

為您的數據庫創建一個觸發器函數:

CREATE OR REPLACE FUNCTION notify_change() RETURNS TRIGGER AS $$
    BEGIN
        SELECT pg_notify('test', TG_TABLE_NAME);
        RETURN NEW;
    END;
$$ LANGUAGE plpgsql;

為您要跟蹤的每個表分配一個觸發器:

CREATE TRIGGER table_change 
    AFTER INSERT OR UPDATE OR DELETE ON table_name
    FOR EACH ROW EXECUTE PROCEDURE notify_change();

如果您可以輪詢數據庫,請按以下步驟操作:

PGConnection con = ...

try (Statement s = con.createStatement()) {
    s.executeUpdate("listen x");
    s.executeUpdate("notify x, 'abc'");
}

for (PGNotification n : con.getNotifications()) {
    System.out.println(String.format("%s, %s, %s", 
        n.getPID(), n.getName(), n.getParameter()));
}

以上將產生類似於:

11796, x, abc
11796, x, xyz

您必須至少運行一條語句才能從連接中獲取新通知。

似乎沒有辦法解決這個問題。 您可以解決這個問題,因為已經按照這些方式提出了一些建議,但最終,您將進行投票。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM