对于
    
    
      JAVA
    
    
      系统中的定时操作有两种实现方式
    
    
      (
    
    
      针对
    
    
      oarcle)
    
    
      :
    
  
  
    
      
        1.
        
                 
        
      
    
    
      通过程序在应用层实现,如
    
    
      quartz
    
    
      ,
    
    
      Timer
    
    
      等
    
  
  
    
      如在
    
    
      spring
    
    
      中:
    
  
  
    
      
            
      
    
    
      <
    
    
      bean 
    
    
      id
    
    
      =
    
    
      "abcJobDetail" 
    
    
      class
    
    
      =
    
    
      "org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
            
      
    
    
      <
    
    
      property 
    
    
      name
    
    
      =
    
    
      "targetObject"
    
    
      ><
    
    
      ref 
    
    
      bean
    
    
      =
    
    
      "abcService"
    
    
      /></
    
    
      property
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
            
      
    
    
      <
    
    
      property 
    
    
      name
    
    
      =
    
    
      "targetMethod"
    
    
      ><
    
    
      value
    
    
      >
    
    
      abc
    
    
      </
    
    
      value
    
    
      ></
    
    
      property
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
    
    
      </
    
    
      bean
    
    
      >
    
    
      
               
      
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
    
    
      <
    
    
      bean 
    
    
      id
    
    
      =
    
    
      "abcTrigger" 
    
    
      class
    
    
      =
    
    
      "org.springframework.scheduling.quartz.CronTriggerBean"
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
          
      
    
    
      <
    
    
      property 
    
    
      name
    
    
      =
    
    
      "jobDetail"
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
            
      
    
    
      <
    
    
      ref 
    
    
      bean
    
    
      =
    
    
      "abcJobDetail"
    
    
      />
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
          
      
    
    
      </
    
    
      property
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
          
      
    
    
      <
    
    
      property 
    
    
      name
    
    
      =
    
    
      "cronExpression"
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
            
      
    
    
      <
    
    
      value
    
    
      >
    
    
      0 0 4 * * ?
    
    
      </
    
    
      value
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
          
      
    
    
      </
    
    
      property
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
    
    
      </
    
    
      bean
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
    
    
      <
    
    
      bean 
    
    
      class
    
    
      =
    
    
      "org.springframework.scheduling.quartz.SchedulerFactoryBean"
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
          
      
    
    
      <
    
    
      property 
    
    
      name
    
    
      =
    
    
      "triggers"
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
            
      
    
    
      <
    
    
      list
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
              
      
    
    
      <
    
    
      ref 
    
    
      local
    
    
      =
    
    
      "abcTrigger"
    
    
      />
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
            
      
    
    
      </
    
    
      list
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
      
          
      
    
    
      </
    
    
      property
    
    
      >
    
    
      <o:p></o:p>
    
  
  
    
      
            
      
    
    
      </
    
    
      bean
    
    
      >
    
  
  
    
      
        2.
        
                 
        
      
    
    
      直接在数据库层实现,先写个存储过程,然后创建一个
    
    
      job
    
    
      ,定时执行该存储过程。
    
  
  
    
      具体方法如下:
    
  
  
    
      DBMS_JOB
    
    
      系统包是
    
    
      Oracle
    
    
      “任务队列”子系统的
    
    
      API
    
    
      编程接口。
    
    
      DBMS_JOB
    
    
      包对于任务队列提供了下面这些功能:提交并且执行一个任务、改变任务的执行参数以及删除或者临时挂起任务等。
    
  
  
    
      <v:shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></v:path><o:lock aspectratio="t" v:ext="edit"></o:lock></v:shapetype><v:shape id="_x0000_i1025" style="WIDTH: 387pt; HEIGHT: 258.75pt" type="#_x0000_t75"><v:imagedata o:title="ScreenShot053" src="file:///C:\DOCUME~1\pengch\LOCALS~1\Temp\msohtml1\01\clip_image001.gif"></v:imagedata></v:shape>
    
  
  
    
      <o:p> 
      
        
      
      </o:p>
    
  
  
    
      DBMS_JOB
    
    
      包中所有的过程都有一组相同的公共参数,用于定义任务,任务的运行时间以及任务定时运行的时间间隔。这些公共任务定义参数见表
    
    
      2
    
    
      所示。
    
  
  
    
      
        
      
    
  
  
    
      <v:shape id="_x0000_i1026" style="WIDTH: 405pt; HEIGHT: 128.25pt" type="#_x0000_t75"><v:imagedata o:title="ScreenShot054" src="file:///C:\DOCUME~1\pengch\LOCALS~1\Temp\msohtml1\01\clip_image002.gif"></v:imagedata></v:shape>
    
  
  
    下面我们来详细讨论这些参数的意义及用法。
  
  
    
          
      
        
          1
        
      
    
    
      
        、
        
          job
        
        参数
      
    
    
      
        
        
      
      
        
        
      
    
    
      job
    
    是一个整数,用来唯一地标示一个任务。该参数既可由用户指定也可由系统自动赋予,这完全取决于提交任务时选用了那一个任务提交过程。
    
      DBMS_JOB.SUBMIT
    
    过程通过获得序列
    
      SYS.JOBSEQ
    
    的下一个值来自动赋予一个任务号。该任务号是作为一个
    
      OUT
    
    参数返回的,所以调用者随后可以识别出提交的任务。而
    
      DBMS_JOB.ISUBMIT
    
    过程则由调用者给任务指定一个识别号,这时候,任务号的唯一性就完全取决于调用者了。
  
  
    
            
      
        
           2
        
      
    
    
      
        、
        
          what
        
      
    
    
      
    
    
      what
    
    参数是一个可以转化为合法
    
      PL/SQL
    
    调用的字符串,该调用将被任务队列自动执行。在
    
      what
    
    参数中,如果使用文字字符串,则该字符串必须用单引号括起来。
    
       what
    
    参数也可以使用包含我们所需要字符串值的
    
      VARCHAR2
    
    变量。实际的
    
      PL/SQL
    
    调用必须用分号隔开。在
    
      PL/SQL
    
    调用中如果要嵌入文字字符串,则必须使用两个单引号。
  
  
    
          what
    
    参数的长度在
    
      Oracle7.3
    
    中限制在
    
      2000
    
    个字节以内,在
    
      Oracle 8.0
    
    以后,扩大到了
    
      4000
    
    个字节,这对于一般的应用已完全足够。该参数的值一般情况下都是对一个
    
      PL/SQL
      
        
          
            存储
          
        
      
    
    过程的调用。在实际应用中,尽管可以使用大匿名
    
      Pl/SQL
    
    块,但建议大家最好不要这样使用。还有一个实际经验就是最好将存储过程调用封装在一个匿名块中,这样可以避免一些比较莫名错误的产生。我来举一个例子,一般情况下,
    
      what
    
    参数可以这样引用:
  
  
    
          what =>
    
    ‘
    
      my_procedure
    
    (
    
      parameter1
    
    );’
  
  
    
          
    
    但是比较安全的引用,应该这样写:
  
  
    
          what =>
    
    ‘
    
      begin my_procedure
    
    (
    
      parameter1
    
    );
    
       end
    
    ;’
  
  
    
            
      
        
           3
        
      
    
    
      
        、
        
          next_date Next_
        
      
    
    
      
        
      
      
        
        
      
    
    
      date
    
    参数是用来调度任务队列中该任务下一次运行的时间。这个参数对于
    
      DBMS_JOB.SUBMIT
    
    和
    
      DBMS_JOB.BROKEN
    
    这两个过程缺省为系统当前时间,也就是说任务将立即运行。
  
  
    
          
    
    当将一个任务的
    
      next_date
    
    参数赋值为
    
      null
    
    时,则该任务下一次运行的时间将被指定为<st1:chsdate w:st="on" year="4000" month="1" day="1" islunardate="False" isrocdate="False">
    
      4000
    
    年
    
      1
    
    月
    
      1
    
    日</st1:chsdate>,也就是说该任务将永远不再运行。在大多数情况下,这可能是我们不愿意看到的情形。但是,换一个角度来考虑,
    
      如果想在任务队列中保留该任务而又不想让其运行,将
      
        next_date
      
      设置为
      
        null
      
      却是一个非常简单的办法。
      
        <o:p></o:p>
      
    
  
  
    
          Next_date
    
    也可以设置为过去的一个时间。这里要注意,系统任务的执行顺序是根据它们下一次的执行时间来确定的,于是将
    
      next_date
    
    参数设置回去就可以达到将该任务排在任务队列前面的目的。这在任务队列进程不能跟上将要执行的任务并且一个特定的任务需要尽快执行时是非常有用的。
  
  
    
      
            4
      
    
    
      
        、
        
          Interval
        
      
    
    
      
        
        
      
      
        
        
      
    
    
       Internal
    
    参数是一个表示
    
      Oracle
    
    合法日期表达式的字符串。这个日期字符串的值在每次任务被执行时算出,算出的日期表达式有两种可能,要么是未来的一个时间要么就是
    
      null.
    
    这里要强调一点:很多开发者都没有意识到
    
      next_date
    
    
      是在一个任务开始时算出的,而不是在任务成功完成时算出的。
      
        <o:p></o:p>
      
    
  
  
    当任务成功完成时,系统通过更新任务队列目录表将前面算出的
    
      next_date
    
    值置为下一次任务要运行的时间。当由
    
      interval
    
    表达式算出
    
      next_date
    
    是
    
      null
    
    时,任务自动从任务队列中移出,不会再继续执行。因此,如果传递一个
    
      null
    
    值给
    
      interval
    
    参数,则该任务仅仅执行一次。
  
  
    
      6. no_parse
    
    参数
  
  
    指示此工作在提交时或执行时是否应进行语法分析
  
  
    
      TRUE
    
    指示此
    
      PL/SQL
    
    代码在它第一次执行时应进行语法分析,
  
  
    而
    
      FALSE
    
    指示本
    
      PL/SQL
    
    代码应立即进行语法分析。
  
  
    
      
      
    
    算法任务重复运行的时间间隔取决于
    
      interval
    
    参数中设置的日期表达式。下面就来详细谈谈该如何设置
    
      interval
    
    参数才能准确满足我们的任务需求。一般来讲,对于一个任务的定时执行,有三种定时要求。
  
  
    
          
    
    在一个特定的时间间隔后,重复运行该任务。
  
  
    
          
    
    在特定的日期和时间运行任务。
  
  
    
          
    
    任务成功完成后,下一次执行应该在一个特定的时间间隔之后。
  
  
    
          
    
    第一种调度任务需求的日期算法比较简单,即
    
      'SYSDATE+n'
    
    ,这里
    
      n
    
    是一个以天为单位的时间间隔。表
    
      6
    
    给出了一些这种时间间隔设置的例子。
  
  
    
      
    
  
  
    
      <v:shape id="_x0000_i1027" style="WIDTH: 380.25pt; HEIGHT: 163.5pt" type="#_x0000_t75"><v:imagedata o:title="" src="file:///C:\DOCUME~1\pengch\LOCALS~1\Temp\msohtml1\01\clip_image003.png"></v:imagedata></v:shape>
    
  
  
    第二种调度任务需求相对于第一种就需要更复杂的时间间隔(
    
      interval
    
    )表达式,表是一些要求在特定的时间运行任务的
    
      interval
    
    设置例子。
  
  
    
       
      
        
      
       <v:shape id="_x0000_i1028" style="WIDTH: 363.75pt; HEIGHT: 229.5pt" type="#_x0000_t75"> <v:imagedata o:title="" src="file:///C:\DOCUME~1\pengch\LOCALS~1\Temp\msohtml1\01\clip_image005.png"></v:imagedata></v:shape>
    
  
    
  
    
      
      
        CREATE
      
      
         
      
      
        OR
      
      
         
      
      
        REPLACE
      
      
          
      
      
        PROCEDURE
      
      
         raise_salary (emp_id 
      
      
        INTEGER
      
      
        , increase 
      
      
        REAL
      
      
        ) 
      
      
        IS
      
      
         
        
        
                current_salary  
      
      
        REAL
      
      
        ; 
        
        
                salary_missing  EXCEPTION; 
        
        
            
      
      
        BEGIN
      
      
         
        
        
                
      
      
        SELECT
      
      
         sal 
      
      
        INTO
      
      
         current_salary 
      
      
        FROM
      
      
         emp 
        
        
                    
      
      
        WHERE
      
      
         empno 
      
      
        =
      
      
         emp_id; 
        
        
                
      
      
        IF
      
      
         current_salary 
      
      
        IS
      
      
         
      
      
        NULL
      
      
         
      
      
        THEN
      
      
         
        
        
                    RAISE salary_missing; 
        
        
        
        
                
      
      
        ELSE
      
      
         
        
        
                    
      
      
        UPDATE
      
      
         emp 
      
      
        SET
      
      
         sal 
      
      
        =
      
      
         sal 
      
      
        +
      
      
         increase 
        
        
                        
      
      
        WHERE
      
      
         empno 
      
      
        =
      
      
         emp_id; 
        
        
                
      
      
        END
      
      
         
      
      
        IF
      
      
        ; 
        
        
            EXCEPTION 
        
        
                
      
      
        WHEN
      
      
         NO_DATA_FOUND 
      
      
        THEN
      
      
         
        
        
                    
      
      
        INSERT
      
      
         
      
      
        INTO
      
      
         emp_audit 
      
      
        VALUES
      
      
         (emp_id, 
      
      
        '
      
      
        No such number
      
      
        '
      
      
        ); 
        
        
                
      
      
        WHEN
      
      
         salary_missing 
      
      
        THEN
      
      
         
        
        
                    
      
      
        INSERT
      
      
         
      
      
        INTO
      
      
         emp_audit 
      
      
        VALUES
      
      
         (emp_id, 
      
      
        '
      
      
        Salary is null
      
      
        '
      
      
        ); 
        
        
            
      
      
        END
      
      
         raise_salary;
        
        
      
     
   
  
  
  
  
  
    
      对于JAVA系统中的定时操作有两种实现方式(针对oarcle)