如何使用Postgres数据库在Java中获得异步/事件驱动的LISTEN/NOTIFY支持?

jas*_*645 31 java postgresql

据我所知,Java中LISTEN/NOTIFY的JDBC驱动程序不支持真正的事件驱动通知.您必须经常轮询数据库以查看是否有新通知.

我有什么选择在Java中(可能是除了JDBC以外的东西?),如果有的话,在没有轮询的情况下以真正的事件驱动方式异步获取通知?

Nei*_*gan 32

使用pgjdbc-ng驱动程序.

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

它支持异步通知,无需轮询.我成功地使用了它.

请参阅http://blog.databasepatterns.com/2014/04/postgresql-nofify-websocket-spring-mvc.html

Oleg也有一个很好的例子


Ole*_*lov 24

这是使用JD. 1.8的com.impossibl.postgres.api(pgjdbc-ng-0.6-complete.jar)的异步模式:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

为数据库创建触发器函数:

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

为要跟踪的每个表分配触发器:

CREATE TRIGGER table_change 
    AFTER INSERT OR UPDATE OR DELETE ON table_name
    FOR EACH ROW EXECUTE PROCEDURE notify_change();
Run Code Online (Sandbox Code Playgroud)

  • 不需要while(true){},除了try循环将终止 - 并关闭Connection - 如果没有东西可以阻止它.连接需要保持打开状态以使NOTIFY消息起作用. (3认同)
  • @SergeiTachenov,您可以使用“NOTIFY”,但其值必须是静态字符串,而“pg_notify()”可以使用静态字符串或变量 (3认同)
  • 我也在你的帖子中做.我可以知道`while(true){}`的意义是什么?我还发布了一个关于我早期问题的类似问题:http://stackoverflow.com/questions/37916489/listen-notify-pgconnection-goes-down-java (2认同)