Подтвердить что ты не робот

Как я могу получить поддержку LISTEN/NOTIFY с поддержкой асинхронных/событийных событий в Java с помощью базы данных Postgres?

Из того, что я могу сказать, драйверы JDBC для LISTEN/NOTIFY в Java НЕ поддерживают истинные уведомления, управляемые событиями. Вы должны периодически опробовать базу данных, чтобы узнать, есть ли новое уведомление.

Какие параметры у меня есть на Java (возможно, что-то другое, чем JDBC?), если они есть, для асинхронного получения уведомлений с помощью истинного события без опроса?

4b9b3361

Ответ 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).