對于
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)