如何使用 Postgres 数据库在 Java 中获得异步/事件驱动的 LISTEN/NOTIFY 支持?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21632243/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I get asynchronous / event-driven LISTEN/NOTIFY support in Java using a Postgres database?
提问by jasons2645
From what I can tell, the JDBC drivers for LISTEN/NOTIFY in Java do NOT support true event-driven notifications. You have to poll the database every so often to see if there's a new notification.
据我所知,Java 中用于 LISTEN/NOTIFY 的 JDBC 驱动程序不支持真正的事件驱动通知。您必须经常轮询数据库以查看是否有新通知。
What options do I have in Java (possibly something other than JDBC?), if any, to get notifications asynchronously in a true event-driven manner without polling?
我在 Java 中有哪些选项(可能是 JDBC 之外的其他选项?),如果有的话,可以在没有轮询的情况下以真正的事件驱动方式异步获取通知?
采纳答案by Neil McGuigan
Use the pgjdbc-ng driver.
使用 pgjdbc-ng 驱动程序。
http://impossibl.github.io/pgjdbc-ng/
http://impossibl.github.io/pgjdbc-ng/
It supports async notifications, without polling. I have used it successfully.
它支持异步通知,无需轮询。我已经成功使用了。
See http://blog.databasepatterns.com/2014/04/postgresql-nofify-websocket-spring-mvc.html
见http://blog.databasepatterns.com/2014/04/postgresql-nofify-websocket-spring-mvc.html
Oleg has a nice example answer as well
Oleg 也有一个很好的示例答案
回答by jasons2645
It appears as though there's no way around this. You can work around it, as several suggestions have been made along those lines, but ultimately, you're going to be polling.
似乎没有办法解决这个问题。您可以解决这个问题,因为已经按照这些方式提出了一些建议,但最终,您将进行投票。
回答by Lukas Eder
If you're OK with polling the database, here's how to do it:
如果您同意轮询数据库,请按以下步骤操作:
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()));
}
The above will yield something like:
以上将产生类似的东西:
11796, x, abc
11796, x, xyz
You have to run at least one statement to get new notifications from the connection.
您必须至少运行一条语句才能从连接中获取新通知。
回答by Oleg Mikhailov
Here's an asynchronous pattern using com.impossibl.postgres.api (pgjdbc-ng-0.6-complete.jar) with JDK 1.8:
这是使用 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 a trigger function for your database:
为您的数据库创建一个触发器函数:
CREATE OR REPLACE FUNCTION notify_change() RETURNS TRIGGER AS $$
BEGIN
SELECT pg_notify('test', TG_TABLE_NAME);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Assign a trigger for every table you want to track:
为您要跟踪的每个表分配一个触发器:
CREATE TRIGGER table_change
AFTER INSERT OR UPDATE OR DELETE ON table_name
FOR EACH ROW EXECUTE PROCEDURE notify_change();