Как я могу получить поддержку LISTEN/NOTIFY с поддержкой асинхронных/событийных событий в Java с помощью базы данных Postgres?
Из того, что я могу сказать, драйверы JDBC для LISTEN/NOTIFY в Java НЕ поддерживают истинные уведомления, управляемые событиями. Вы должны периодически опробовать базу данных, чтобы узнать, есть ли новое уведомление.
Какие параметры у меня есть на Java (возможно, что-то другое, чем JDBC?), если они есть, для асинхронного получения уведомлений с помощью истинного события без опроса?
Ответы
Ответ 1
Используйте драйвер pgjdbc-ng.
http://impossibl.github.io/pgjdbc-ng/
Он поддерживает асинхронные уведомления без опроса. Я использовал его успешно.
См. http://blog.databasepatterns.com/2014/04/postgresql-nofify-websocket-spring-mvc.html
У Олега есть хороший пример ответа
Ответ 2
Здесь показан асинхронный шаблон с использованием 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();
Ответ 3
Кажется, что нет никакого способа обойти это. Вы можете обойти это, так как по этим направлениям было сделано несколько предложений, но в конечном итоге вы собираетесь проводить опрос.
Ответ 4
Если вы в порядке с опросом базы данных, вот как это сделать:
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
Вам нужно запустить хотя бы один оператор, чтобы получать новые уведомления из соединения.
Ответ 5
Это большое ограничение уведомления/прослушивания Postgres и в основном делает его бесполезным для приложений Java. Я предполагаю, что база данных обновляется из другого приложения.
В зависимости от того, как часто обновляется база данных, существует 2 варианта:
-
Если база данных обновляется часто, просто опросите запрос таким образом select * from table where update_timestamp > ?
. Этот столбец должен быть проиндексирован.
-
Если база данных не обновляется, часто делайте приложение, которое обновляет сообщения о публикации обновлений базы данных в брокере сообщений (например, нуль mq).