我正在开发一个客户端/服务器应用程序,使用Android作为客户端,JBoss AS 7.x作为服务器。我通过servlet完成所有这些操作,并且DataSource配置为使用连接池。
其中一个要求是在删除DataSource(Oracle)中的某些数据时立即使客户端会话无效。为此,我正在检查DBMS_ALERT。
据我所知,DBMS_ALERT需要一个轮询机制,它将“挂起”应用程序直到发生通知。所以我的servlet将暂停所有操作并等待通知。如果我错了,请纠正我,因为我对PL / SQL几乎没有经验。
我已经检查了此 question 中提供的资源,但我无法理解正确的选择。
DBMS_ALERT DataSource 端的代码是:
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部分时挂起它(如果它是一个可行的解决方案)?
由于
答案 0 :(得分:2)
如果您查看API documentation中的留言功能,则会显示:
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包)。