我嘗試創建客戶端 - >數據庫通知/更新系統。客戶端是用Java/Hibernate編寫的。通知客戶本人使用觸發器:基於通知的實時PostgreSQL客戶端更新
CREATE OR REPLACE FUNCTION notifyUsers() RETURNS TRIGGER AS $$
DECLARE
data integer;
notification json;
BEGIN
IF (TG_OP = 'DELETE') THEN
data = OLD.id;
ELSE
data = NEW.id;
END IF;
-- Contruct the notification
notification = json_build_object(
'table',TG_TABLE_NAME,
'action', TG_OP,
'id', data);
-- Execute pg_notify(channel, notification)
PERFORM pg_notify('events',notification::text);
-- Result is ignored since this is an AFTER trigger
RETURN NULL;
END;
$$ LANGUAGE 'plpgsql';
CREATE TRIGGER notifyUsersAccountData AFTER INSERT OR UPDATE OR DELETE ON document FOR EACH ROW EXECUTE PROCEDURE notifyUsers();
,但是當通過客戶端收到的通知,我不能確定誰觸發它。 我可以發送任何其他參數,以確定誰觸發它(session_id?在我的應用程序中有自定義用戶,但我想避免發送User.id作爲登錄同一用戶由2 PC將打破我的通知/更新系統)
在通知接收方客戶端更新值後,需要「會話ID」來確定「THIS客戶端」是否進行了更改(當然在這種情況下客戶端不應該更新)或其他人(在此情況下,更新應適用)
編輯 - - -
我想刷新這個話題,因爲它沒有得到解決。調用pg_backend_pid的解決方案有時會中斷,導致「執行SQL查詢的調用程序的PID」與PGNotification.getPid不同。代碼:
public int getSessionPid() {
int lResult = -1;
try
{
connect();
Session session = _sessionFactory.getCurrentSession();
Transaction lTransaction = session.beginTransaction();
SQLQuery lQuery = session.createSQLQuery("SELECT pg_backend_pid()");
List lResultQuery = lQuery.list();
lResult = Integer.parseInt(lResultQuery.get(0).toString());
lTransaction.commit();
}catch(org.hibernate.SessionException e)
{
e.printStackTrace();
}
return lResult;
}
,並在那裏出現比較代碼:
int lPid = Facade.databaseConnector.warehouse.getSessionPid();
for(int i = 0; i < notifications.length; ++i)
{
if(lPid == notifications[i].getPID())
...
此外,我看到的是,在當前的後端連接可見表select * from pg_stat_activity
有按我的方案的一個實例3個連接。
SELECT 1
- 只是爲了通知,因爲沒有「接觸」數據庫進行更新,通知不會被觸發- 一個連接與休眠相關
- 一個連接與SQL查詢數據庫(如插入/相關更新/刪除行等)
所有的後端連接在pg_stat_activity中有不同的端口和PID。
任何想法?
將鏈接添加到https://jdbc.postgresql.org/documentation/head/listennotify.html這個答案。 –
確定它工作正常,但是有沒有辦法避免調用: SELECT pg_backend_pid();我每次收到通知時都會收到 ? –
如果您的會話在收聽活動時持續存在,那麼您可以獲得一次pid並將其存儲在某個變量中。如果你不知道它是否持續,那麼我會通過存儲數組中的所有pid並檢查其內容或者簡單地存儲'oldPid'和比較新鮮的pid來測試它。 –