关于DBMS_ALERT的一些应用

DBMS_ALERT 

 

在DB端Signal一个ALERT,在Application端取得ALERT,再做相应处理。

注:如果要在DB端使用DBMS_ALERT,必须有Object Privileges对应权限。

grant   execute   on   dbms_alert     to   user

 

 

 

DB端:

--PROCEDURE
CREATE OR REPLACE PROCEDURE proc_batch IS
BEGIN
     DBMS_ALERT.signal(
     name => 'batch_send_mail',
     message => 'BATCH');
     COMMIT;
END;

 

--JOB.SUBMIT
VARIABLE jobno number;
BEGIN

  --每隔一天的10点执行。  具体时间是几分之几天。 (1/1440代表每一分钟)
  DBMS_JOB.SUBMIT(:jobno,'proc_batch;',SYSDATE, 'trunc(sysdate)+1+10/24');
  COMMIT;
END;

 

 

--実行job
BEGIN
     DBMS_JOB.RUN(:jobno);
END;

 

 

--非JOB方式的临时测试 (测试App端是否取得ALERT)

BEGIN
     DBMS_ALERT.signal('batch_send_mail',  'BATCH');
     COMMIT;
END;

 

 

 

 

Application端:

 

一、BatchSendMailServlet (由于使用了Spring框架,如果在init同线程中不停等待DB,会使得Bean无法create,后续无法执行,另外新建一个线程,专门用来等待DB)

 

package com.hp.gdcc.jddc.famas.framework.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;


public class BatchSendMailServlet extends HttpServlet {


 public void init() throws ServletException {
  logger.debug("init() method!");

  ListenerThread lt = new ListenerThread();
  Thread thread = new Thread(lt);
  thread.setDaemon(true);
  thread.start();
 }

}

 

 

 

二、ListenerThread (专用于DB等待)

 

package com.hp.gdcc.jddc.famas.framework.servlet;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Types;
import java.util.Date;


import com.hp.gdcc.jddc.famas.com.batch.SendMailService;
import com.hp.gdcc.jddc.famas.com.consts.BeanConstants;
import com.hp.gdcc.jddc.famas.com.service.ICommonBusinessService;
import com.hp.gdcc.jddc.famas.com.util.ApplicationUtil;

public class ListenerThread implements Runnable {



 private static final String ALERT = "batch_send_mail";


 private static final String ALERT_STATUS = "BATCH";


 private static Connection con;

 

 public void run() {

  //由于使用weblogic的JNDI,先去调用一个方法访问DB,如果没有取得或是抛出异常,让线程进行Sleep,10秒后继续访问DB,直到JNDI可用,break出死循环

  this.threadSleep();

 

  //调用DBMS_ALERT,取得返回的ALERT

  this.callDatabase();
 }

 

 private void threadSleep() {
  ICommonBusinessService commonService = (ICommonBusinessService) ApplicationUtil
    .getBean(BeanConstants.BEAN_COM_BUSI_SERVICE);
  while (true) {
   try {
    Date date = commonService.getSysDate();
    if (date != null) {
     logger.debug("date =" + date);
     break;
    } else {
     logger.debug("sleep wait JNDI - 1");
     Thread.sleep(10000);
    }
   } catch (Exception e) {
    try {
     logger.debug("sleep wait JNDI - 2");
     Thread.sleep(10000);
    } catch (Exception ex) {
     logger.debug(ex);
    }
   }
  }
 }

 

 private void callDatabase() {
  try {
   logger.debug("callDatabase() method!");
   Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
   String url = "jdbc:oracle:thin:@jddccq:1521:FAMAS";
   con = DriverManager.getConnection(url, "FAMAS", "FAMAS");

   // DBMS_ALERT.REGISTER
   // - 指定した名前のアラートをこのセッションで受け取ることを定義する
   String storedproc = "{call DBMS_ALERT.REGISTER(?)}";
   CallableStatement cstmt1 = con.prepareCall(storedproc);
   cstmt1.setString(1, ALERT);
   cstmt1.executeUpdate();

   // ALERT MSG
   String outputStr = null;

   CallableStatement cstmt2;

   // DBMS_ALERT.WAITANY
   // メッセージの受信待ち
   // ここでは、一つの待ちプロセスで複数の種類のメッセージを受け取り、
   // メッセージの内容で処理を分ける。
   String storedproc2 = "{call DBMS_ALERT.WAITANY(?,?,?,?)}";
   cstmt2 = con.prepareCall(storedproc2);
   // 第1パラメータ(OUT) - アラートの名前
   cstmt2.registerOutParameter(1, Types.VARCHAR);
   // 第2パラメータ(OUT) - メッセージの内容
   cstmt2.registerOutParameter(2, Types.VARCHAR);
   // 第3パラメータ(OUT) - 実行結果。0ならアラート受信。1ならタイムアウト。
   cstmt2.registerOutParameter(3, Types.INTEGER);
   // 第4パラメータ(IN) - タイムアウト時間(秒数)
   cstmt2.setInt(4, 300);

 

   // stopSyncが実行されると completeフラグがセットされる。
   // それまでは無限ループとなる。

   while (true) {
    logger.debug("Listenning!!!");
    // アラートはトランザクションがコミットした時点で送受信される
    con.commit();
    // 上で指定したDBMS_ALERT.WAITANYプロシジャの実行
    cstmt2.executeUpdate();
    if (cstmt2.getInt(3) == 1) {
     // タイムアウトによって終了した場合の処理
     logger.debug("TIME OUT! WAITING!");
    } else {
     // アラート受信で終了した場合、アラートの名前で処理を分ける
     // cstmt2.getString(1) == ALERT
     outputStr = cstmt2.getString(2);
     logger.debug("msg = " + outputStr);

     // メール送付機能を呼び出し
     if (ALERT_STATUS.equals(outputStr)) {

      // 得到了DB送出的ALERT,这里执行自定的处理
      this.doSomething();
     }
    }
   }

  } catch (Exception e) {
   logger.debug(e);
  }
 }


}

 

 

 三、web.xml

 

 <servlet>
     <servlet-name>batchServlet</servlet-name>
     <servlet-class>com.hp.gdcc.jddc.famas.framework.servlet.BatchSendMailServlet</servlet-class>

     <!--启动优先级低于ActionServlet,越大越低-->
     <load-on-startup>3</load-on-startup>
</servlet>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值