對(duì)于
JAVA
系統(tǒng)中的定時(shí)操作有兩種實(shí)現(xiàn)方式
(
針對(duì)
oarcle)
:
1.
??????
通過(guò)程序在應(yīng)用層實(shí)現(xiàn),如
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.
??????
直接在數(shù)據(jù)庫(kù)層實(shí)現(xiàn),先寫(xiě)個(gè)存儲(chǔ)過(guò)程,然后創(chuàng)建一個(gè)
job
,定時(shí)執(zhí)行該存儲(chǔ)過(guò)程。
具體方法如下:
DBMS_JOB
系統(tǒng)包是
Oracle
“任務(wù)隊(duì)列”子系統(tǒng)的
API
編程接口。
DBMS_JOB
包對(duì)于任務(wù)隊(duì)列提供了下面這些功能:提交并且執(zhí)行一個(gè)任務(wù)、改變?nèi)蝿?wù)的執(zhí)行參數(shù)以及刪除或者臨時(shí)掛起任務(wù)等。
<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
包中所有的過(guò)程都有一組相同的公共參數(shù),用于定義任務(wù),任務(wù)的運(yùn)行時(shí)間以及任務(wù)定時(shí)運(yùn)行的時(shí)間間隔。這些公共任務(wù)定義參數(shù)見(jiàn)表
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>
下面我們來(lái)詳細(xì)討論這些參數(shù)的意義及用法。
???
1
、
job
參數(shù)
job
是一個(gè)整數(shù),用來(lái)唯一地標(biāo)示一個(gè)任務(wù)。該參數(shù)既可由用戶指定也可由系統(tǒng)自動(dòng)賦予,這完全取決于提交任務(wù)時(shí)選用了那一個(gè)任務(wù)提交過(guò)程。
DBMS_JOB.SUBMIT
過(guò)程通過(guò)獲得序列
SYS.JOBSEQ
的下一個(gè)值來(lái)自動(dòng)賦予一個(gè)任務(wù)號(hào)。該任務(wù)號(hào)是作為一個(gè)
OUT
參數(shù)返回的,所以調(diào)用者隨后可以識(shí)別出提交的任務(wù)。而
DBMS_JOB.ISUBMIT
過(guò)程則由調(diào)用者給任務(wù)指定一個(gè)識(shí)別號(hào),這時(shí)候,任務(wù)號(hào)的唯一性就完全取決于調(diào)用者了。
??????
2
、
what
what
參數(shù)是一個(gè)可以轉(zhuǎn)化為合法
PL/SQL
調(diào)用的字符串,該調(diào)用將被任務(wù)隊(duì)列自動(dòng)執(zhí)行。在
what
參數(shù)中,如果使用文字字符串,則該字符串必須用單引號(hào)括起來(lái)。
what
參數(shù)也可以使用包含我們所需要字符串值的
VARCHAR2
變量。實(shí)際的
PL/SQL
調(diào)用必須用分號(hào)隔開(kāi)。在
PL/SQL
調(diào)用中如果要嵌入文字字符串,則必須使用兩個(gè)單引號(hào)。
??? what
參數(shù)的長(zhǎng)度在
Oracle7.3
中限制在
2000
個(gè)字節(jié)以內(nèi),在
Oracle 8.0
以后,擴(kuò)大到了
4000
個(gè)字節(jié),這對(duì)于一般的應(yīng)用已完全足夠。該參數(shù)的值一般情況下都是對(duì)一個(gè)
PL/SQL
存儲(chǔ)
過(guò)程的調(diào)用。在實(shí)際應(yīng)用中,盡管可以使用大匿名
Pl/SQL
塊,但建議大家最好不要這樣使用。還有一個(gè)實(shí)際經(jīng)驗(yàn)就是最好將存儲(chǔ)過(guò)程調(diào)用封裝在一個(gè)匿名塊中,這樣可以避免一些比較莫名錯(cuò)誤的產(chǎn)生。我來(lái)舉一個(gè)例子,一般情況下,
what
參數(shù)可以這樣引用:
??? what =>
‘
my_procedure
(
parameter1
);’
???
但是比較安全的引用,應(yīng)該這樣寫(xiě):
??? what =>
‘
begin my_procedure
(
parameter1
);
end
;’
??????
3
、
next_date Next_
date
參數(shù)是用來(lái)調(diào)度任務(wù)隊(duì)列中該任務(wù)下一次運(yùn)行的時(shí)間。這個(gè)參數(shù)對(duì)于
DBMS_JOB.SUBMIT
和
DBMS_JOB.BROKEN
這兩個(gè)過(guò)程缺省為系統(tǒng)當(dāng)前時(shí)間,也就是說(shuō)任務(wù)將立即運(yùn)行。
???
當(dāng)將一個(gè)任務(wù)的
next_date
參數(shù)賦值為
null
時(shí),則該任務(wù)下一次運(yùn)行的時(shí)間將被指定為<st1:chsdate w:st="on" year="4000" month="1" day="1" islunardate="False" isrocdate="False">
4000
年
1
月
1
日</st1:chsdate>,也就是說(shuō)該任務(wù)將永遠(yuǎn)不再運(yùn)行。在大多數(shù)情況下,這可能是我們不愿意看到的情形。但是,換一個(gè)角度來(lái)考慮,
如果想在任務(wù)隊(duì)列中保留該任務(wù)而又不想讓其運(yùn)行,將
next_date
設(shè)置為
null
卻是一個(gè)非常簡(jiǎn)單的辦法。
<o:p></o:p>
??? Next_date
也可以設(shè)置為過(guò)去的一個(gè)時(shí)間。這里要注意,系統(tǒng)任務(wù)的執(zhí)行順序是根據(jù)它們下一次的執(zhí)行時(shí)間來(lái)確定的,于是將
next_date
參數(shù)設(shè)置回去就可以達(dá)到將該任務(wù)排在任務(wù)隊(duì)列前面的目的。這在任務(wù)隊(duì)列進(jìn)程不能跟上將要執(zhí)行的任務(wù)并且一個(gè)特定的任務(wù)需要盡快執(zhí)行時(shí)是非常有用的。
??? 4
、
Interval
Internal
參數(shù)是一個(gè)表示
Oracle
合法日期表達(dá)式的字符串。這個(gè)日期字符串的值在每次任務(wù)被執(zhí)行時(shí)算出,算出的日期表達(dá)式有兩種可能,要么是未來(lái)的一個(gè)時(shí)間要么就是
null.
這里要強(qiáng)調(diào)一點(diǎn):很多開(kāi)發(fā)者都沒(méi)有意識(shí)到
next_date
是在一個(gè)任務(wù)開(kāi)始時(shí)算出的,而不是在任務(wù)成功完成時(shí)算出的。
<o:p></o:p>
當(dāng)任務(wù)成功完成時(shí),系統(tǒng)通過(guò)更新任務(wù)隊(duì)列目錄表將前面算出的
next_date
值置為下一次任務(wù)要運(yùn)行的時(shí)間。當(dāng)由
interval
表達(dá)式算出
next_date
是
null
時(shí),任務(wù)自動(dòng)從任務(wù)隊(duì)列中移出,不會(huì)再繼續(xù)執(zhí)行。因此,如果傳遞一個(gè)
null
值給
interval
參數(shù),則該任務(wù)僅僅執(zhí)行一次。
6. no_parse
參數(shù)
指示此工作在提交時(shí)或執(zhí)行時(shí)是否應(yīng)進(jìn)行語(yǔ)法分析
TRUE
指示此
PL/SQL
代碼在它第一次執(zhí)行時(shí)應(yīng)進(jìn)行語(yǔ)法分析,
而
FALSE
指示本
PL/SQL
代碼應(yīng)立即進(jìn)行語(yǔ)法分析。
算法任務(wù)重復(fù)運(yùn)行的時(shí)間間隔取決于
interval
參數(shù)中設(shè)置的日期表達(dá)式。下面就來(lái)詳細(xì)談?wù)勗撊绾卧O(shè)置
interval
參數(shù)才能準(zhǔn)確滿足我們的任務(wù)需求。一般來(lái)講,對(duì)于一個(gè)任務(wù)的定時(shí)執(zhí)行,有三種定時(shí)要求。
???
在一個(gè)特定的時(shí)間間隔后,重復(fù)運(yùn)行該任務(wù)。
???
在特定的日期和時(shí)間運(yùn)行任務(wù)。
???
任務(wù)成功完成后,下一次執(zhí)行應(yīng)該在一個(gè)特定的時(shí)間間隔之后。
???
第一種調(diào)度任務(wù)需求的日期算法比較簡(jiǎn)單,即
'SYSDATE+n'
,這里
n
是一個(gè)以天為單位的時(shí)間間隔。表
6
給出了一些這種時(shí)間間隔設(shè)置的例子。
<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>
第二種調(diào)度任務(wù)需求相對(duì)于第一種就需要更復(fù)雜的時(shí)間間隔(
interval
)表達(dá)式,表是一些要求在特定的時(shí)間運(yùn)行任務(wù)的
interval
設(shè)置例子。
?
?<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;
對(duì)于JAVA系統(tǒng)中的定時(shí)操作有兩種實(shí)現(xiàn)方式(針對(duì)oarcle)