【发布时间】:2018-02-18 17:47:37
【问题描述】:
我尝试创建客户端 -> 数据库通知/更新系统。客户端是用 Java / Hibernate 编写的。为了通知客户,我使用了触发器:
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”来确定是“这个客户端”进行了更改(当然在这种情况下客户端不应该更新)还是其他人(在这种情况下应该应用更新)
编辑 - - -
我想刷新这个话题,因为它没有解决。调用 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。
有什么想法吗?
【问题讨论】:
标签: java sql postgresql hibernate