監視/通知

監視と通知は、同一のPostgreSQL™データベースにアクセスするプロセスの集合に対し、単純なシグナルやプロセス間通信機構を提供します。 通知に関する詳細はサーバ主文書を参照してください。 本節では、通知に関するJDBC固有の点についてのみ取り扱います。

標準のLISTENNOTIFYUNLISTENコマンドは標準のStatementインタフェース経由で発行されます。 通知を受け取り、受け取った通知を処理するには、ConnectionをPostgreSQL™固有の拡張を行ったPGConnectionインタフェースにキャストしなければなりません。 これにより、getNotifications()メソッドを使用して、発生した通知を受信することができます。

注意

JDBCドライバでは、非同期の通知を受け取ることができず、通知が発生したかどうかをバックエンドに問い合わせなければならないという制限があることに注意してください。

例 9.2. 通知の受信

import java.sql.*;

public class NotificationTest {

	public static void main(String args[]) throws Exception {
		Class.forName("org.postgresql.Driver");
		String url = "jdbc:postgresql://localhost:5432/test";


                // 2つの接続を作成します。1つは通知側、もう1つは受信側で、
                // 接続を跨った通信を示します。なお、実際は1つの接続だけ
                // でも正常に動作します。
		Connection lConn = DriverManager.getConnection(url,"test","");
		Connection nConn = DriverManager.getConnection(url,"test","");


                // 2つのスレッドを作成します。1つは通知を発行し、もう1つ
                // で通知を受信します。
		Listener listener = new Listener(lConn);
		Notifier notifier = new Notifier(nConn);
		listener.start();
		notifier.start();
	}

}

class Listener extends Thread {

	private Connection conn;
	private org.postgresql.PGConnection pgconn;

	Listener(Connection conn) throws SQLException {
		this.conn = conn;
		this.pgconn = (org.postgresql.PGConnection)conn;
		Statement stmt = conn.createStatement();
		stmt.execute("LISTEN mymessage");
		stmt.close();
	}

	public void run() {
		while (true) {
			try {

                                // ダミーの問い合わせを発行し、バックエンドと
                                // 通信し、待ち状態の通知を受け取ります。
				Statement stmt = conn.createStatement();
				ResultSet rs = stmt.executeQuery("SELECT 1");
				rs.close();
				stmt.close();

				org.postgresql.PGNotification notifications[] = pgconn.getNotifications();
				if (notifications != null) {
					for (int i=0; i<notifications.length; i++) {
						System.out.println("Got notification: " + notifications[i].getName());
					}
				}


                                // 新しい通知を再度検査する前にしばらく待機し
                                // ます。
				Thread.sleep(500);
			} catch (SQLException sqle) {
				sqle.printStackTrace();
			} catch (InterruptedException ie) {
				ie.printStackTrace();
			}
		}
	}

}

class Notifier extends Thread {

	private Connection conn;

	public Notifier(Connection conn) {
		this.conn = conn;
	}

	public void run() {
		while (true) {
			try {
				Statement stmt = conn.createStatement();
				stmt.execute("NOTIFY mymessage");
				stmt.close();
				Thread.sleep(2000);
			} catch (SQLException sqle) {
				sqle.printStackTrace();
			} catch (InterruptedException ie) {
				ie.printStackTrace();
			}
		}
	}

}