如何使用Postgres数据库在Java中获得异步/事件驱动的LISTEN/NOTIFY支持?
2022-09-01 01:00:54
据我所知,Java中用于 LISTEN/NOTIFY 的 JDBC 驱动程序不支持真正的事件驱动通知。您必须经常轮询数据库,以查看是否有新的通知。
在Java中,我有什么选择(可能是JDBC以外的其他东西?),如果有的话,可以以真正的事件驱动方式异步获取通知而无需轮询?
据我所知,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
源代码: https://bitbucket.org/neilmcg/postgresql-websocket-example
奥列格也有一个很好的例子答案
下面是一个使用 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();