1

我正在开发使用 Android 作为客户端和 JBoss AS 7.x 作为服务器的客户端/服务器应用程序。我通过一个 servlet 完成所有这些工作,并且 DataSource 被配置为使用连接池。

要求之一是在删除 DataSource(Oracle) 中的某些数据时立即使客户端会话无效。为此,我正在检查 DBMS_ALERT。

据我所知,DBMS_ALERT 需要一种轮询机制,该机制将“挂起”应用程序,直到发生通知。所以我的 servlet 将停止所有操作并等待通知。如果我错了,请纠正我,因为我对 PL/SQL 几乎没有经验。

我已经检查了这个问题中提供的资源,但我不明白什么是正确的做法。


DBMS_ALERT数据源端的代码是:

CREATE OR REPLACE TRIGGER apps0000_datuser_biur
    BEFORE  INSERT OR UPDATE OR DELETE on apps0000_t
    REFERENCING NEW AS NEW OLD AS OLD
    for EACH ROW
begin
    if (deleting) then
        DBMS_ALERT.signal('appdelete',:old.APPS_PACKAGE);
    end if;
end;


DBMS_ALERT servlet端的代码是(如果我在这里有问题,请纠正我):

try {
    String strDSName1 = "java:/OracleDSJNDI";
    ctx = new InitialContext();
    ds1 = (javax.sql.DataSource) ctx.lookup(strDSName1);
} catch (Exception e) {
    System.out.println("ERROR getting 1'st DS : " + e);
}

 conn = ds1.getConnection();

 String sql = null;
 String message = null;
 String status = null;

 sql = "{call dbms_alert.register('appdelete')}";
 CallableStatement cs1 = conn.prepareCall(sql);
 cs1.execute();
 sql = "{call dbms_alert.waitone('appdelete', ?, ?, ?)}";

 CallableStatement cs2 = conn.prepareCall(sql);
 cs2.registerOutParameter(1, Types.VARCHAR);
 cs2.registerOutParameter(2, Types.VARCHAR);
 cs2.registerOutParameter(3, Types.VARCHAR);

 int x = 0;

 while (x == 0) {
     cs2.execute();
     String Result = cs2.getString(1);
     System.out.print(Result + "\n");
 }


我的问题是:如何在我的 servlet 中实现它而不导致它在到达 DBMS_ALERT 部分时挂起(如果它是一个可行的解决方案)?

谢谢

4

1 回答 1

2

如果您查看API 文档中的消息函数,它会显示:

DBMS_ALERT.WAITONE (
   name      IN   VARCHAR2,
   message   OUT  VARCHAR2,
   status    OUT  INTEGER,
   timeout   IN   NUMBER DEFAULT MAXWAIT);

“超时”参数默认为永远。评论指出:

timeout

Maximum time to wait for an alert.

If the named alert does not occurs before timeout seconds, this returns a status of 1.

因此,您可以将此超时设置为 # 秒,然后循环轮询。但是,我认为这是一种糟糕的方法,因为您只是使用轮询来消耗网络和应用程序/服务器资源。如果可能的话,我会考虑使用允许完全异步处理的 Oracle Advanced Queuing(参见 DBMS_AQ 包)。

于 2013-09-12T22:11:25.207 回答