數(shù)據(jù)庫(kù)系統(tǒng)原理與實(shí)踐 課件 第6章 數(shù)據(jù)庫(kù)編程_第1頁(yè)
數(shù)據(jù)庫(kù)系統(tǒng)原理與實(shí)踐 課件 第6章 數(shù)據(jù)庫(kù)編程_第2頁(yè)
數(shù)據(jù)庫(kù)系統(tǒng)原理與實(shí)踐 課件 第6章 數(shù)據(jù)庫(kù)編程_第3頁(yè)
數(shù)據(jù)庫(kù)系統(tǒng)原理與實(shí)踐 課件 第6章 數(shù)據(jù)庫(kù)編程_第4頁(yè)
數(shù)據(jù)庫(kù)系統(tǒng)原理與實(shí)踐 課件 第6章 數(shù)據(jù)庫(kù)編程_第5頁(yè)
已閱讀5頁(yè),還剩192頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

6.1數(shù)據(jù)庫(kù)服務(wù)器編程了解數(shù)據(jù)庫(kù)編程掌握數(shù)據(jù)庫(kù)服務(wù)器程序語法和結(jié)構(gòu)掌握數(shù)據(jù)庫(kù)函數(shù)編程掌握數(shù)據(jù)庫(kù)游標(biāo)編程【本節(jié)學(xué)習(xí)目標(biāo)】6.1數(shù)據(jù)庫(kù)服務(wù)器編程簡(jiǎn)介數(shù)據(jù)庫(kù)服務(wù)器編程是指編寫運(yùn)行在數(shù)據(jù)庫(kù)服務(wù)器端的應(yīng)用程序;數(shù)據(jù)庫(kù)服務(wù)程序包括存儲(chǔ)過程、用戶自定義函數(shù)、觸發(fā)器、事件調(diào)度器、事務(wù)控制、異常處理、動(dòng)態(tài)SQL和安全性管理等內(nèi)容。數(shù)據(jù)庫(kù)服務(wù)器程序有利于實(shí)現(xiàn)復(fù)雜的數(shù)據(jù)操作和邏輯,提高數(shù)據(jù)庫(kù)應(yīng)用程序的性能和安全性。數(shù)據(jù)庫(kù)服務(wù)器編程使用特定的數(shù)據(jù)庫(kù)編程語言(如PL/SQL、PL/pgSQL等)編寫。6.1.1數(shù)據(jù)庫(kù)PL/pgSQL語言PL/pgSQL(ProceduralLanguage/PostgreSQL)是postgreSQL數(shù)據(jù)庫(kù)的面向過程的編程語言。提供了編寫在服務(wù)器端執(zhí)行的函數(shù)和存儲(chǔ)過程的方法。PL/pgSQL的主要語法特點(diǎn)PL/pgSQL代碼由塊組成,每個(gè)塊包含聲明、可執(zhí)行和異常處理部分。PL/pgSQL支持多種數(shù)據(jù)類型,包括PostgreSQL的內(nèi)置數(shù)據(jù)類型(如整數(shù)、浮點(diǎn)數(shù)、字符串等)和用戶自定義數(shù)據(jù)類型。PL/pgSQL提供了豐富的控制結(jié)構(gòu),如條件語句(IF、CASE)、循環(huán)語句(FOR、WHILE、LOOP)和異常處理(BEGINEXCEPTION...END)。PL/pgSQL允許開發(fā)者在代碼中嵌入SQL語句,以便執(zhí)行查詢、插入、更新和刪除等操作。PL/pgSQL支持創(chuàng)建用戶自定義函數(shù)和存儲(chǔ)過程。PL/pgSQL允許開發(fā)者創(chuàng)建觸發(fā)器函數(shù),用于在特定事件發(fā)生時(shí)自動(dòng)執(zhí)行。觸發(fā)器函數(shù)可以用于實(shí)現(xiàn)數(shù)據(jù)完整性約束、審計(jì)日志等功能。6.1.2PL/pgSQL變量聲明在使用變量之前,必須在PL/pgSQL塊的DECLARE下進(jìn)行聲明,聲明變量的語法:變量名[CONSTANT]變量類型[NOTNULL][DEFAULT|:=expression];useridINTEGER:=1;firstnameVARCHAR(20):='Tom';LastnameVARCHAR(20):='Doe';PaymentNUMERIC(6,2):=120.6;例如:特殊類型的聲明聲明與指定表的行相同類型的變量,稱為行類型變量(簡(jiǎn)稱行類型)。常用于數(shù)據(jù)庫(kù)查詢的結(jié)果賦值給變量,定義語法格式為:變量名表名%ROWTYPE;stuinforstudent%ROWTYPE;例如:特殊類型的聲明(續(xù))用戶可以聲明變量為記錄類型,記錄型變量與行類型變量類似,但是它們沒有預(yù)定義的結(jié)構(gòu)。變量聲明格式為:變量名RECORD;data_recRECORD;例如:特殊類型的聲明(續(xù))PostgreSQL可使用已定義變量來定義新變量,其定義方法為:變量1變量2%TYPE;v_names_name%TYPE;例如:6.1.3PL/pgSQL控制語句(1)IF語句用于條件判斷。根據(jù)條件的真假執(zhí)行相應(yīng)的代碼塊。IFp_age<18THENRETURN'未成年人';ELSIFp_age>=18ANDp_age<60THENRETURN'成年人';ELSERETURN'老年人';ENDIF;例如:6.1.3PL/pgSQL控制語句(續(xù))(2)CASE語句用于多條件判斷。根據(jù)條件的真假執(zhí)行相應(yīng)的代碼塊。CASEWHENp_score>=90THENgrade:='A';WHENp_score>=80THENgrade:='B';WHENp_score>=70THENgrade:='C';ELSEgrade:='D';ENDCASE;例如:6.1.3PL/pgSQL控制語句(續(xù))(3)LOOP語句用于無條件循環(huán)。循環(huán)內(nèi)部可以使用EXIT或RETURN語句跳出循環(huán)。DECLAREcounterINTEGER:=1;BEGINLOOPRAISENOTICE'%',counter;counter:=counter+1;IFcounter>p_maxTHENEXIT;ENDIF;ENDLOOP;END;例如:6.1.3PL/pgSQL控制語句(續(xù))(4)WHILE語句用于條件循環(huán)。當(dāng)條件為真時(shí),執(zhí)行循環(huán)體。DECLAREresultINTEGER:=1;BEGINWHILEp_num>0LOOPresult:=result*p_num;p_num:=p_num-1;ENDLOOP;END;例如:6.1.3PL/pgSQL控制語句(續(xù))(5)FOR語句用于遍歷范圍或記錄集??梢允褂谜麛?shù)范圍或查詢結(jié)果作為循環(huán)變量。DECLAREsumINTEGER:=0;BEGINFORiIN1..p_maxLOOPsum:=sum+i*i;ENDLOOP;END;例如:6.1.3PL/pgSQL控制語句(續(xù))(6)異常處理用于捕獲和處理異常。可在BEGIN...EXCEPTION...END塊中定義異常處理。DECLAREresultNUMERIC;BEGINBEGINresult:=p_num1/p_num2;EXCEPTIONWHENdivision_by_zeroTHENRAISENOTICE'Divisionbyzeroisnotallowed.';result:=NULL;END;END;例如:6.1.4PL/pgSQL函數(shù)編程使用PL/pgSQL語言可以編寫自定義函數(shù);函數(shù)是在數(shù)據(jù)庫(kù)服務(wù)器上定義的一種特殊類型的程序,用于執(zhí)行特定功能并返回一個(gè)值;用戶自定義函數(shù)可以在SQL查詢中像內(nèi)置函數(shù)一樣使用,提高了查詢的靈活性和可讀性;與C語言的函數(shù)一樣,具有函數(shù)名、輸入?yún)?shù)和輸出參數(shù)。數(shù)據(jù)庫(kù)函數(shù)編程的優(yōu)點(diǎn)通過PL/pgSQL編寫函數(shù)存儲(chǔ)在數(shù)據(jù)庫(kù)服務(wù)器,既具有SQL語言簡(jiǎn)單易用的優(yōu)點(diǎn),又具有處理復(fù)雜邏輯過程的能力;由于存儲(chǔ)數(shù)據(jù)庫(kù)服務(wù)器,因此調(diào)用執(zhí)行數(shù)據(jù)庫(kù)服務(wù)器的函數(shù),能消除客戶端和服務(wù)器之間的額外通信,戶端不需要的中間結(jié)果不必由服務(wù)器向客戶端傳送;能夠避免多次調(diào)用的重復(fù)編譯或解析。創(chuàng)建數(shù)據(jù)庫(kù)函數(shù)的語法CREATE[ORREPLACE]FUNCTIONname([[argmode][argname]argtype[{DEFAULT|=}default_expr][,...]])[RETURNSretype|RETURNSTABLE(column_namecolumn_type[,...])]AS$$//$$用于聲明函數(shù)的實(shí)際代碼的開始DECLARE--聲明段BEGIN--函數(shù)體語句END;$$LANGUAGElang_name;//$$表明代碼的結(jié)束,LANGUAGE后面指明所用的編程語言(1)name:要?jiǎng)?chuàng)建的函數(shù)名;(3)argmode:函數(shù)參數(shù)的模式可以為IN、OUT或INOUT,缺省值是IN。(4)argname:形式參數(shù)的名字。(5)RETURNS:返回值;RETURNSTABLE:返回二維表(2)ORREPLACE:覆蓋同名的函數(shù);自定義不帶參數(shù)的函數(shù)示例創(chuàng)建一個(gè)名為countRecords()的函數(shù)統(tǒng)計(jì)STUDENT表的記錄數(shù)。CREATEORREPLACEFUNCTIONcountRecords()RETURNSintegerAS$count$declarecountinteger;BEGIN

SELECTcount(*)intocountFROMSTUDENT;RETURNcount;END;

$count$LANGUAGEplpgsql;自定義帶參數(shù)的函數(shù)示例傳遞給函數(shù)參數(shù)都可以用$1、$2的標(biāo)識(shí)符來表示。為了增加可讀性,可以為參數(shù)聲明別名,別名和數(shù)字標(biāo)識(shí)符均可指向該參數(shù)值。CREATEFUNCTIONdiscount(salePricereal)RETURNSrealAS$$BEGINRETURNsalePrice*0.85;END;$$LANGUAGEplpgsql;定義輸入?yún)?shù)為“銷售價(jià)格”的函數(shù),返回折扣價(jià)格。執(zhí)行數(shù)據(jù)庫(kù)函數(shù)如果程序員需要在查詢窗口執(zhí)行函數(shù),語法形式如下:

select

函數(shù)名(參數(shù));或者:

select*from函數(shù)名(參數(shù));例如:selectcountRecords();或者:select*fromcountRecords();執(zhí)行數(shù)據(jù)庫(kù)函數(shù)(續(xù))如果需要在函數(shù)或存儲(chǔ)過程中調(diào)用數(shù)據(jù)庫(kù)函數(shù),語法形式如下:selectinto自定義變量from函數(shù)名(參數(shù));CREATEORREPLACEFUNCTIONtestExec()returnsintegerAS$$declarerecinteger;BEGIN

selectintoreccountRecords();

//如果不關(guān)心countRecords()的返回值,則可用PERFORMcountRecords()代替;returnrec;END;

$$LANGUAGEplpgsql;理解游標(biāo)的基本概念掌握游標(biāo)聲明、打開、讀取、關(guān)閉的方法掌握數(shù)據(jù)庫(kù)游標(biāo)編程的基本步驟6.1.5PL/pgSQL游標(biāo)編程什么是游標(biāo)?(1)游標(biāo)(Cursor)是一種臨時(shí)的數(shù)據(jù)庫(kù)對(duì)象;(2)用來存放從數(shù)據(jù)庫(kù)表中查詢返回的數(shù)據(jù)記錄;(3)提供了從結(jié)果集中提取并分別處理每一條記錄的機(jī)制;(4)游標(biāo)總是與一條SQL查詢語句相關(guān)聯(lián);(5)游標(biāo)包括:SQL語言的查詢結(jié)果,指向特定記錄的指針。第1步:聲明游標(biāo)(1)在存儲(chǔ)過程中游標(biāo)類型的變量。例如:游標(biāo)變量refcursor;refcursor是關(guān)鍵字;

此時(shí),游標(biāo)變量還沒有綁定查詢語句,因此不能訪問游標(biāo)變量。(2)使用游標(biāo)專有的聲明語法,如:

游標(biāo)名

CURSOR[(arguments)]FORquery;其中arguments為由逗號(hào)分隔的參數(shù)列表,用于打開游標(biāo)時(shí)向游標(biāo)傳遞參數(shù),類似于存儲(chǔ)過程或函數(shù)的形式參數(shù);query是select數(shù)據(jù)查詢語句,返回的值存儲(chǔ)在游標(biāo)變量中。游標(biāo)聲明的示例例如:(1)curStudentCURSORFORSELECT*FROMstudent;(2)curStudentOneCURSOR(keyinteger)IS

SELECT*FROMstudentWHERESID=key;第2步:打開游標(biāo)(1)OPENFOR:

其聲明形式為:

OPENunbound_cursorFOR

query;打開未綁定的游標(biāo)變量,其query查詢語句是返回記錄的SELECT語句。例如:OPENcurVars1

FOR

SELECT*FROMstudentWHERESID=mykey;(2)OPENFOREXECUTE其聲明形式為:OPENunbound_cursorFOREXECUTEquery-string;打開未綁定的游標(biāo)變量。EXECUTE將動(dòng)態(tài)執(zhí)行查詢字符串。例如:

OPENcurVars1FOREXECUTE'SELECT*FROM'||quote_ident($1);

注意:$1是指由存儲(chǔ)過程傳遞的第1個(gè)參數(shù)。第2步:打開游標(biāo)(續(xù))(3)打開一個(gè)綁定的游標(biāo),其聲明形式為:

OPENbound_cursor[(argument_values)];僅適用于綁定的游標(biāo)變量,只有當(dāng)該變量在聲明時(shí)包含接收參數(shù),才能以傳遞參數(shù)的形式打開該游標(biāo),參數(shù)將傳入到游標(biāo)聲明的查詢語句中,例如:

OPENcurStudent;

OPENcurStudentOne(‘20160230302001’);第3步:從游標(biāo)中獲取數(shù)據(jù)其聲明形式為:FETCHcursorINTOtarget;FETCH命令從游標(biāo)中讀取下一行記錄的數(shù)據(jù)到目標(biāo)中,讀取成功與否,可通過PL/SQL內(nèi)置系統(tǒng)變量FOUND來判斷。

例如:

FETCHcurVars1INTOrowvar;--rowvar為行變量

FETCHcurStudentINTOSID,Sname,sex;

請(qǐng)注意:游標(biāo)的屬性列必須與目標(biāo)列的數(shù)量一致,并且類型兼容。第4步:關(guān)閉游標(biāo)CLOSEcursorName;當(dāng)游標(biāo)數(shù)據(jù)不再需要時(shí),需要關(guān)閉游標(biāo),以釋放其占有的系統(tǒng)資源,主要是釋放游標(biāo)數(shù)據(jù)所占用的內(nèi)存資源,cursorName是游標(biāo)名。

例如:CLOSEcurStudent;需要注意:當(dāng)游標(biāo)被關(guān)閉后,如果需要再次讀取游標(biāo)的數(shù)據(jù),需要重新使用open打開游標(biāo),這時(shí)游標(biāo)重新查詢返回新的結(jié)果。

在函數(shù)過程中使用游標(biāo)的示例11、下面例子使用不帶參數(shù)的游標(biāo),查詢student表的學(xué)號(hào)、學(xué)生姓名和性別。

執(zhí)行函數(shù)的結(jié)果在函數(shù)中使用游標(biāo)的示例22、下面示例使用帶參數(shù)的游標(biāo),從成績(jī)表中查詢分?jǐn)?shù)大于某給定值的學(xué)號(hào)和課程號(hào)。執(zhí)行函數(shù)的結(jié)果本節(jié)學(xué)習(xí)結(jié)束!6.2數(shù)據(jù)庫(kù)存儲(chǔ)過程了解存儲(chǔ)過程的概念掌握存儲(chǔ)過程創(chuàng)建方法掌握存儲(chǔ)過程的修改和刪除方法掌握PostgreSQL簡(jiǎn)單并發(fā)編程理解存儲(chǔ)過程的優(yōu)化原則【本節(jié)學(xué)習(xí)目標(biāo)】一、什么是存儲(chǔ)過程存儲(chǔ)過程(StoredProcedure)是一種數(shù)據(jù)庫(kù)的對(duì)象;由一組能完成特定功能的SQL語句集構(gòu)成;是把經(jīng)常會(huì)被重復(fù)使用的SQL語句邏輯塊封裝起來,經(jīng)編譯后,存儲(chǔ)在數(shù)據(jù)庫(kù)服務(wù)器端;當(dāng)被再次調(diào)用時(shí),而不需要再次編譯;當(dāng)客戶端連接到數(shù)據(jù)庫(kù)時(shí),用戶通過指定存儲(chǔ)過程的名字并給出參數(shù),數(shù)據(jù)庫(kù)就可以找到相應(yīng)的存儲(chǔ)過程予以調(diào)用。二、創(chuàng)建存儲(chǔ)過程不同的數(shù)據(jù)庫(kù)系統(tǒng)創(chuàng)建存儲(chǔ)過程的語法存在差異;許多數(shù)據(jù)庫(kù)為創(chuàng)建存儲(chǔ)過程和函數(shù)提供不同命令;PostgreSQL早期版本使用CREATEFUNCTION命令創(chuàng)建函數(shù)。PostgreSQL10.0以后使用CREATEFUNCTION命令創(chuàng)建存儲(chǔ)過程。三、創(chuàng)建存儲(chǔ)過程的語法CREATEORREPLACEPROCEDUREprocedureName([IN|OUT|INOUT]PnamedataType,...)AS$$DECLARE變量1數(shù)據(jù)類型:=初始值1;變量2數(shù)據(jù)類型:=初始值2;

BEGIN--程序執(zhí)行體語句寫在這里;END;$$LANGUAGEplpgsql

//指明存儲(chǔ)過程結(jié)束,告訴編譯器使用PL/pgSQL語言實(shí)現(xiàn)的(1)procedureName:存儲(chǔ)過程名;(3)IN、OUT或INOUT參數(shù)模式。IN為輸入?yún)?shù);OUT為輸出參數(shù)缺省值是IN。(4)Pname:形式參數(shù)的名字。(5)dataType:該存儲(chǔ)過程參數(shù)的數(shù)據(jù)類型。(2)ORREPLACE:覆蓋同名的存儲(chǔ)過程;四、創(chuàng)建存儲(chǔ)過程的示例

假設(shè)使用存儲(chǔ)過程實(shí)現(xiàn)銀行轉(zhuǎn)賬,客戶銀行余額信息存在accounts表中,轉(zhuǎn)賬記錄信息存在translists表中;銀行轉(zhuǎn)賬包括三個(gè)主要操作,首先檢查轉(zhuǎn)出賬戶的余額是否充足,如果大于轉(zhuǎn)出金額,將客戶的余額減去轉(zhuǎn)賬金額;然后給轉(zhuǎn)入賬戶的余額加上轉(zhuǎn)賬金額;最后記錄轉(zhuǎn)賬信息,以供后期備查。四、創(chuàng)建存儲(chǔ)過程的示例(續(xù))(1)假設(shè)系統(tǒng)設(shè)計(jì)時(shí)需要?jiǎng)?chuàng)建如下客戶銀行余額信息表accounts;droptableifexistsaccounts;createtableaccounts(

idSERIAL,

--客戶ID號(hào)usernamevarchar(100)notnull, --客戶姓名balancedec(15,2)notnull, --賬戶余額primarykey(id));四、創(chuàng)建存儲(chǔ)過程的示例(續(xù))(2)下面是創(chuàng)建客戶轉(zhuǎn)賬信息表translists;droptableifexiststranslists;createtabletranslists(idSERIALprimarykey, --轉(zhuǎn)賬記錄IDsendidint, --轉(zhuǎn)出客戶的IDsendnamevarchar(100)notnull, --轉(zhuǎn)出客戶的姓名recidint, --轉(zhuǎn)入客戶的IDrecnamevarchar(100)notnull, --轉(zhuǎn)入客戶的姓名transdatetimestamp(0), --轉(zhuǎn)賬時(shí)間transamountdec(15,2)notnull --轉(zhuǎn)賬金額);四、創(chuàng)建存儲(chǔ)過程的示例(續(xù))(3)為了測(cè)試程序,預(yù)先在客戶余額信息表accounts中插入兩條客戶余額信息;insertintoaccounts(username,balance)values('Bob',10000);insertintoaccounts(username,balance)values('Alice',10000);四、創(chuàng)建存儲(chǔ)過程的示例(續(xù))四、創(chuàng)建存儲(chǔ)過程的示例(續(xù))五、修改存儲(chǔ)過程(1)修改存儲(chǔ)過程的名字ALTERPROCEDUREname([[argmode][argname]argtype[,...]])RENAMETOnew_name;(2)修改存儲(chǔ)過程的所有者ALTERPROCEDUREname([[argmode][argname]argtype[,...]])OWNERTOnew_owner;(3)修改存儲(chǔ)過程所屬模式ALTERPROCEDUREname([[argmode][argname]argtype[,...]])SETSCHEMAnew_schema;五、修改存儲(chǔ)過程(續(xù))把名字為displayStudent(integer),參數(shù)類型為integer的存儲(chǔ)過程名改為display_stu;再將所有者修改為dba;然后把所屬模式改變?yōu)閟tuDB。ALTERPROCEDUREdisplayStudent(integer)RENAMETOdisplay_stu;ALTERPROCEDUREdisplay_stu(integer)OWNERTOdba;ALTERPROCEDUREdisplay_stu(integer)SETSCHEMAstuDB;六、刪除存儲(chǔ)過程如果程序員需要?jiǎng)h除存儲(chǔ)過程,語法形式如下:DROPPROCEDURE[IFEXISTS]name[([[argmode][argname]argtype[,...]])][,...];主要參數(shù):(1)IFEXISTS:如果指定的存儲(chǔ)過程不存在,那么發(fā)出提示信息。(2)name:現(xiàn)存的存儲(chǔ)過程名稱。(3)argmode:參數(shù)的模式:IN(缺省),OUT,INOUT,VARIADIC。請(qǐng)注意,實(shí)際并不注意OUT參數(shù),因?yàn)榕袛啻鎯?chǔ)過程的身份只需要輸入?yún)?shù)。(4)argname:參數(shù)的名字。請(qǐng)注意,實(shí)際上并不注意參數(shù)的名字,因?yàn)榕袛嗪瘮?shù)的身份只需要輸入?yún)?shù)的數(shù)據(jù)類型。(5)argtype:如果有的話,是存儲(chǔ)過程參數(shù)的類型。六、刪除存儲(chǔ)過程(續(xù))示例:假如需要?jiǎng)h除前面定義的存儲(chǔ)過程TRANSFERDROPPROCEDUREIFEXISTSTRANSFER(SENDERint,RECEIVERint,AMOUNTdec);七、存儲(chǔ)過程的并發(fā)編程在數(shù)據(jù)庫(kù)并發(fā)環(huán)境中,有時(shí)需要用到并發(fā)編程。實(shí)現(xiàn)并發(fā)編程主要依賴于PostgreSQL的事務(wù)和鎖機(jī)制。PL/pgSQL語言不提供線程或并行執(zhí)行功能,但通過使用事務(wù)和鎖來確保在并發(fā)環(huán)境下數(shù)據(jù)的一致性和完整性。七、存儲(chǔ)過程的并發(fā)編程(續(xù))FORUPDATE:用于排他鎖定,防止其他事務(wù)同時(shí)修改或鎖定相同的數(shù)據(jù)。在SELECT語句中使用FORUPDATE子句來實(shí)現(xiàn)。FORSHARE:用于共享鎖定,允許多個(gè)事務(wù)同時(shí)讀取相同的數(shù)據(jù),但阻止其他事務(wù)對(duì)數(shù)據(jù)進(jìn)行更新。在SELECT語句中使用FORSHARE子句來實(shí)現(xiàn)。FORNOKEYUPDATE:這種鎖與FORUPDATE類似,但它不會(huì)阻止其他事務(wù)對(duì)非鍵列進(jìn)行更新。在SELECT語句中使用FORNOKEYUPDATE子句來實(shí)現(xiàn)。FORKEYSHARE:用于共享鎖定,允許多個(gè)事務(wù)同時(shí)讀取相同的數(shù)據(jù),但阻止其他事務(wù)對(duì)鍵列進(jìn)行更新。在SELECT語句中使用FORKEYSHARE子句來實(shí)現(xiàn)。七、存儲(chǔ)過程的并發(fā)編程示例在火車票購(gòu)票系統(tǒng)中,數(shù)據(jù)庫(kù)名為trainsdb,火車票的余票信息存儲(chǔ)在train_tickets表中,使用PL/pgSQL并發(fā)編程,確保車票數(shù)據(jù)的一致性和完整性。創(chuàng)建名為trainsdb的PostgreSQL數(shù)據(jù)庫(kù),并在其中創(chuàng)建名為train_tickets的表;向train_tickets表中插入一條初始記錄。七、存儲(chǔ)過程的并發(fā)編程示例(續(xù))創(chuàng)建名為buy_train_ticket的PL/pgSQL過程,該函數(shù)將模擬購(gòu)票操作,并使用并發(fā)控制:八、存儲(chǔ)過程的優(yōu)化原則(1)控制存儲(chǔ)過程的復(fù)雜度(2)避免在存儲(chǔ)過程中過度使用臨時(shí)表(3)盡量使用參數(shù)化查詢(4)合理使用索引來優(yōu)化存儲(chǔ)過程的性能(5)編寫存儲(chǔ)過程時(shí)遵循最佳實(shí)踐和安全原則本節(jié)學(xué)習(xí)結(jié)束!6.3數(shù)據(jù)庫(kù)觸發(fā)器了解觸發(fā)器的基本概念掌握postgreSQL觸發(fā)器創(chuàng)建、修改、刪除的方法理解觸發(fā)器的執(zhí)行過程【本節(jié)學(xué)習(xí)目標(biāo)】一、觸發(fā)器的基本概念

觸發(fā)器是特殊類型的存儲(chǔ)過程,主要由操作事件(INSERT、UPDATE、DELETE)觸發(fā)而被自動(dòng)執(zhí)行。

觸發(fā)器可以實(shí)現(xiàn)比約束更復(fù)雜的數(shù)據(jù)完整性,經(jīng)常用于加強(qiáng)數(shù)據(jù)的完整性約束和業(yè)務(wù)規(guī)則。觸發(fā)器本身是一個(gè)特殊的事務(wù)單位。觸發(fā)器的特點(diǎn)與表相關(guān)聯(lián):必須定義在表或視圖上。

自動(dòng)觸發(fā):由執(zhí)行INSERT、DELETE、UPDATE操作時(shí)觸發(fā)

不能直接調(diào)用,也不能傳遞或接受參數(shù)

是事務(wù)的一部分:觸發(fā)器和觸發(fā)語句作為可在觸發(fā)器內(nèi)回滾的單個(gè)事務(wù)。觸發(fā)器的分類按觸發(fā)的語句分為:

INSERT觸發(fā)器、DELETE觸發(fā)器、UPDATE觸發(fā)器用戶動(dòng)作

insertdeleteupdate應(yīng)用表inserttriggerdeletetriggerupdatetrigger數(shù)據(jù)庫(kù)觸發(fā)器的分類(續(xù))觸發(fā)器執(zhí)行的次數(shù)可分:

(1)語句級(jí)觸發(fā)器:由關(guān)鍵字FOREACHSTATEMENT聲明,在觸發(fā)器作用的表上執(zhí)行一條SQL語句時(shí),該觸發(fā)器只執(zhí)行一次,即使是修改了零行數(shù)據(jù)的SQL,也會(huì)導(dǎo)致相應(yīng)的觸發(fā)器執(zhí)行。如果都沒有被指定,F(xiàn)OREACHSTATEMENT會(huì)是默認(rèn)值。

(2)行級(jí)觸發(fā)器:由關(guān)鍵字FOREACHROW標(biāo)記的觸發(fā)器,當(dāng)觸發(fā)器作用的表的數(shù)據(jù)發(fā)生變化時(shí),每變化一行就會(huì)執(zhí)行一次觸發(fā)器。例如,假設(shè)學(xué)生成績(jī)表有DELETE觸發(fā)器,當(dāng)在該表執(zhí)行DELETE語句刪除記錄時(shí),如果刪除了20條記錄,則將導(dǎo)致DELETE觸發(fā)器被執(zhí)行20次。觸發(fā)器的分類(續(xù))按觸發(fā)的時(shí)間分為三類:(1)BEFORE觸發(fā)器:在觸發(fā)事件之前執(zhí)行觸發(fā)器。(2)AFTER觸發(fā)器:在觸發(fā)事件之后執(zhí)行觸發(fā)器。(3)INSTEADOF觸發(fā)器:當(dāng)觸發(fā)事件發(fā)生后,執(zhí)行觸發(fā)器中指定的函數(shù),而不是執(zhí)行產(chǎn)生觸發(fā)事件的SQL語句,從而替代產(chǎn)生觸發(fā)事件的SQL操作。在表或視圖上,對(duì)于INSERT、UPDATE或DELETE三種觸發(fā)事件,每種最多可以定義一個(gè)INSTEADOF觸發(fā)器INSTEADOF觸發(fā)器觸發(fā)器相關(guān)的特殊變量(1)NEW

數(shù)據(jù)類型是RECORD。對(duì)于行級(jí)觸發(fā)器,它存有INSERT或UPDATE操作產(chǎn)生的新的數(shù)據(jù)行。對(duì)于語句級(jí)觸發(fā)器,它的值是NULL。(2)OLD數(shù)據(jù)類型是RECORD。對(duì)于行級(jí)觸發(fā)器,它存有被UPDATE或DELETE操作修改或刪除的舊的數(shù)據(jù)行。對(duì)于語句級(jí)觸發(fā)器,它的值是NULL。(3)TG_OP數(shù)據(jù)類型是text;是值為INSERT、UPDATE、DELETE的一個(gè)字符串,它說明觸發(fā)器是為哪個(gè)操作引發(fā)。二、PostgreSQL創(chuàng)建觸發(fā)器的基本語法CREATETRIGGER觸發(fā)器名

{BEFORE|AFTER|INSTEADOF}ON表名[FOR[EACH]{ROW|STATEMENT}]

EXECUTEPROCEDURE存儲(chǔ)過程名(參數(shù)列表)(1)指明所定義的觸發(fā)器名

(2)

BEFORE|AFTER|INSTEADOF指明觸發(fā)器被觸發(fā)的時(shí)間(3)ON表名指明觸發(fā)器所依附的表(4)

FOREACH{ROW|STATEMENT}指明觸發(fā)器被觸發(fā)的次數(shù)(5)

EXECUTEPROCEDURE存儲(chǔ)過程名(參數(shù)列表)指明觸發(fā)時(shí)所執(zhí)行的存儲(chǔ)過程三、PostgreSQL創(chuàng)建觸發(fā)器的基本步驟:(1)檢查數(shù)據(jù)庫(kù)中將要?jiǎng)?chuàng)建的觸發(fā)器所依附的表或視圖是否存在,如果不存在,必須首先創(chuàng)建該表或視圖。(2)創(chuàng)建觸發(fā)器被觸發(fā)時(shí)所要執(zhí)行的觸發(fā)器函數(shù),該函數(shù)的類型必須是TRIGGER型,是觸發(fā)器的執(zhí)行函數(shù)。但要注意,有些數(shù)據(jù)庫(kù)不需要獨(dú)立定義觸發(fā)器函數(shù),而是在創(chuàng)建觸發(fā)器時(shí),定義觸發(fā)器的過程體。(3)創(chuàng)建觸發(fā)器,一般需要指明觸發(fā)器依附的表,觸發(fā)器被觸發(fā)執(zhí)行的時(shí)間,觸發(fā)器是行級(jí)觸發(fā)器還是語句級(jí)觸發(fā)器,觸發(fā)器執(zhí)行需要滿足的條件。四、創(chuàng)建觸發(fā)器的示例假設(shè)有stu_score表存儲(chǔ)學(xué)生的課程成績(jī),其表結(jié)構(gòu)如下,同時(shí)插入如下數(shù)據(jù):CREATETABLEstu_score(sidcharacter(10)NOTNULL,cidcharacter(10)NOTNULL,scorenumeric(5,1),CONSTRAINTstu_score_pkeyPRIMARYKEY(sid,cid))四、創(chuàng)建觸發(fā)器的例子(續(xù))為了防止非法修改stu_score表的課程成績(jī),創(chuàng)建audit_score表記錄stu_score表的成績(jī)變化,其表結(jié)構(gòu)如下:CREATETABLEaudit_score(usernamecharacter(20),--用戶名sidcharacter(10),cidcharacter(10),updatetimetext,--修改的時(shí)間oldscorenumeric(5,1),--修改前的成績(jī)newscorenumeric(5,1)--修改后的成績(jī))四、創(chuàng)建觸發(fā)器的例子(續(xù))現(xiàn)在創(chuàng)建觸發(fā)器函數(shù)score_audit()四、創(chuàng)建觸發(fā)器的示例(續(xù))

接下來在stu_score表上創(chuàng)建觸發(fā)器score_audit_triger

CREATETRIGGERscore_audit_triger

AFTERINSERTORUPDATEORDELETEONstu_score

FOREACHROW

EXECUTEPROCEDUREscore_audit();五、驗(yàn)證觸發(fā)器的執(zhí)行將課程號(hào)為1201的課程成績(jī)?cè)黾?分

updatestu_scoresetscore=score+1wherecid='1201';stu_scoreaudit_score四、驗(yàn)證觸發(fā)器的執(zhí)行(續(xù))將刪除課程號(hào)為1501的課程成績(jī)

deletefromstu_scorewherecid='1501';stu_scoreaudit_score四、驗(yàn)證觸發(fā)器的執(zhí)行(續(xù))錄入學(xué)號(hào)14503的同學(xué)的1201號(hào)課程成績(jī)

INSERTINTOstu_score(sid,cid,score)VALUES('14503','1201',83);stu_scoreaudit_score五、觸發(fā)器的修改

ALTERTRIGGERnameON

table_name

RENAMETOnew_name主要參數(shù)說明:(1)name:需要修改的現(xiàn)有觸發(fā)器的名稱。(2)table_name:該觸發(fā)器作用的表的名字。(3)new_name:現(xiàn)有觸發(fā)器的新名字。

例如:將上述定義的觸發(fā)器改名為score_audit_trigALTERTRIGGERscore_audit_triggerONstu_scoreRENAMETOscore_audit_trig;六、觸發(fā)器的刪除

DROPTRIGGER[IFEXISTS]nameONtable_name

[CASCADE|RESTRICT]主要參數(shù)說明:(1)IFEXISTS:如果指定的觸發(fā)器不存在,那么發(fā)出提示而不是拋出錯(cuò)誤。(2)name:要?jiǎng)h除的觸發(fā)器名。(3)table_name:觸發(fā)器定義所依附的表的名稱。(5)CASCADE:級(jí)聯(lián)刪除依賴于觸發(fā)器的對(duì)象;沒有明確哪類對(duì)象依賴觸發(fā)器。(6)RESTRICT:如果有依賴對(duì)象存在,那么拒絕刪除。該參數(shù)缺省是拒絕刪除。

例如:將上述觸發(fā)器score_audit_trig刪除,同時(shí)級(jí)聯(lián)刪除依賴觸發(fā)器的對(duì)象。

DROPTRIGGERIFEXISTSscore_audit_trig

ONstu_score

CASCADE;本節(jié)學(xué)習(xí)結(jié)束!6.4應(yīng)用程序編程訪問數(shù)據(jù)庫(kù)JDBC數(shù)據(jù)庫(kù)連接技術(shù)理解應(yīng)用程序使用JDBC訪問數(shù)據(jù)庫(kù)的步驟掌握J(rèn)ava使用JDBC連接數(shù)據(jù)庫(kù)的方法嵌入式SQL數(shù)據(jù)庫(kù)訪問編程【本節(jié)學(xué)習(xí)目標(biāo)】一、什么是JDBCJDBC(JavaDataBaseConnectivity,Java數(shù)據(jù)庫(kù)連接)技術(shù)的簡(jiǎn)稱,是一種用于執(zhí)行SQL語句的JavaAPI。它由一組用Java編程語言編寫的類和接口組成。這個(gè)API由java.sql.*包中的一些類和接口組成,它為數(shù)據(jù)庫(kù)開發(fā)人員提供了一個(gè)標(biāo)準(zhǔn)的API,使他們能夠用純JavaAPI來編寫數(shù)據(jù)庫(kù)應(yīng)用程序。注意:使用JDBC訪問數(shù)據(jù)庫(kù)需要相應(yīng)數(shù)據(jù)庫(kù)的JDBC驅(qū)動(dòng)程序。二、JDBC工作原理

JDBC接口層

JDBC驅(qū)動(dòng)層

J2EE應(yīng)用

JDBCAPI

數(shù)據(jù)庫(kù)JDBC驅(qū)動(dòng)程序

數(shù)據(jù)庫(kù)

程序員開發(fā)

SUN公司ORACLE公司

數(shù)據(jù)庫(kù)廠商

應(yīng)用層

三、JDBC程序訪問數(shù)據(jù)庫(kù)步驟應(yīng)用程序開始導(dǎo)入java.sql包加載并注冊(cè)驅(qū)動(dòng)程序創(chuàng)建Connection對(duì)象創(chuàng)建Statement對(duì)象執(zhí)行SQL語句關(guān)閉ResultSet

對(duì)象關(guān)閉Statement對(duì)象關(guān)閉Connection對(duì)象使用ResultSet對(duì)象返回結(jié)果結(jié)束(1)加載驅(qū)動(dòng)加載JDBC驅(qū)動(dòng)是通過調(diào)用方法:Class.forName("驅(qū)動(dòng)名字")下面是PostgreSQL數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序加載語句:Class.forName("org.postgresql.Driver");(2)建立連接與數(shù)據(jù)庫(kù)建立連接的方法是調(diào)用DriverManager.getConnection(Stringurl)方法。下面與PostgreSQL數(shù)據(jù)庫(kù)建立連接的語句:StringURL="jdbc:postgresql://localhost:5432/testdb";StringuserName="myuser";StringpassWord="sa";connectionconn=DriverManager.getConnection(URL,userName,passWord);(3)創(chuàng)建Statement對(duì)象可以用Connection對(duì)象的方法createStatement()創(chuàng)建Statement。示例如下:

Statementstmt=conn.createStatement();(4)執(zhí)行SQL語句創(chuàng)建了Statement對(duì)象,就可以向Statement對(duì)象發(fā)送SQL語句。主要掌握兩種執(zhí)行SQL語句的方法:executeQuery()、executeUpdate()executeQuery():返回語句執(zhí)行后的單個(gè)結(jié)果集的,所以通常用于select語句

executeUpdate()返回值是一個(gè)整數(shù),指示受影響的行數(shù)(可以用于update、insert、delete語句)。示例如下:Statementstmt=conn.createStatement();Stringsql="INSERTINTOpublic.student(sid,sname,gender,birthday,major,phone)"+"VALUES('2017001','張山','男','1998-10-10','軟件工程',)";stmt.executeUpdate(sql);(5)ResultSet保存結(jié)果集ResultSet對(duì)象它被稱為結(jié)果集,它代表符合SQL語句條件的所有行,并且它通過一套getXXX方法提供了對(duì)這些行中數(shù)據(jù)的訪問。ResultSet里的數(shù)據(jù)一行一行排列,每行有多個(gè)字段,并且有一個(gè)記錄指針,指針?biāo)傅臄?shù)據(jù)行叫做當(dāng)前數(shù)據(jù)行,我們只能來操作當(dāng)前的數(shù)據(jù)行。我們?nèi)绻胍〉媚骋粭l記錄,就要使用ResultSet的next()方法,如果我們想要得到ResultSet里的所有記錄,就應(yīng)該使用while循環(huán)。示例代碼如下:Statementstmt=conn.createStatement();Stringsql="SELECTid,name,ageFROMcompany";ResultSetrs=stmt.executeQuery(sql);(6)關(guān)閉連接作為一種好的編程風(fēng)格,在不需要ResultSet對(duì)象、Statement對(duì)象和Connection對(duì)象時(shí),應(yīng)該顯式地關(guān)閉它們。關(guān)閉這些對(duì)象的方法為:close()

;示例:rs.close();

//關(guān)閉結(jié)果集對(duì)象stmt.close();

//關(guān)閉執(zhí)行對(duì)象conn.close();

//關(guān)閉連接對(duì)象四、在Eclipse下使用JDBC連接數(shù)據(jù)庫(kù)在PostgreSQL官網(wǎng)下載JDBC驅(qū)動(dòng)程序包postgresql-42.2.2.jar在Eclipse中創(chuàng)建工程PostgreSQL;在PostgreSQL工程中創(chuàng)建jdbclib目錄,并將postgresql-42.2.2.jar拷貝到該目錄;并在工程中做如右圖配置五、Java使用JDBC連接數(shù)據(jù)庫(kù)的例子五、Java使用JDBC連接數(shù)據(jù)庫(kù)的例子(續(xù))五、Java使用JDBC連接數(shù)據(jù)庫(kù)的例子運(yùn)行結(jié)果了解SQL與宿主語言的關(guān)系理解嵌入式SQL的處理過程理解嵌入式SQL與主語言之間的通信理解并掌握在Java語言中嵌入執(zhí)行SQL語句六、嵌入式SQL數(shù)據(jù)庫(kù)訪問編程1、嵌入式SQL與宿主語言(1)SQL語言具有很強(qiáng)的查詢處理能力,而邏輯表達(dá)的能力很弱,界面編程能力也很弱。(2)如JAVA,C/C++等高級(jí)語言具有很強(qiáng)邏輯表達(dá)能力,能實(shí)現(xiàn)復(fù)雜的處理邏輯,同時(shí)具有較強(qiáng)的用戶界面實(shí)現(xiàn)功能。(3)為了使程序語言同時(shí)具有它的優(yōu)點(diǎn),在JAVA、C/C++等高級(jí)語言中嵌入SQL語句,稱高級(jí)語言為宿主語言。(4)由DBMS的預(yù)編譯器掃描識(shí)別處理SQL語句,把SQL語句轉(zhuǎn)換成主語言調(diào)用語句,以使主語言編譯程序能識(shí)別它,最后由主語言的編譯程序?qū)⒄麄€(gè)源程序編譯成目標(biāo)碼,然后連接(Link)處理生成裝載模塊。2、嵌入式SQL的處理過程(1)嵌入式SQL是一個(gè)語句級(jí)接口,通過程序訪問的數(shù)據(jù)庫(kù)模式必須在編寫程序時(shí)已知,以便構(gòu)造SQL語句。例如,程序員必須知道數(shù)據(jù)表名稱、列名稱及它的域。(2)對(duì)于嵌入式SQL,RDBMS一般采用預(yù)編譯方法處理,即由RDBMS的預(yù)處理程序?qū)υ闯绦蜻M(jìn)行掃描,識(shí)別出嵌入的SQL語句,把它們轉(zhuǎn)換成主語言調(diào)用語句,以使主語言編譯程序能識(shí)別它們,然后由主語言的編譯程序?qū)⒓兊闹髡Z言編譯成目標(biāo)碼。3、嵌入式SQL與主語言之間的通信將SQL嵌入到高級(jí)語言中混合編程,SQL語句負(fù)責(zé)操縱數(shù)據(jù)庫(kù),高級(jí)語言語句負(fù)責(zé)控制流程。這時(shí)程序中會(huì)含有兩種不同的計(jì)算模型的語句,從而需要二者之間建立通信。數(shù)據(jù)庫(kù)工作單元與源程序工作單元之間的通信主要包括:(1)向主語言傳遞SQL語句的執(zhí)行狀態(tài)信息,使主語言能夠根據(jù)此信息控制程序流程,主要用SQL通信區(qū)實(shí)現(xiàn)(2)主語言向SQL語句提供參數(shù),主要用主變量實(shí)現(xiàn)(3)將SQL語句查詢數(shù)據(jù)庫(kù)的結(jié)果傳回主語言處理,主要用主變量和游標(biāo)實(shí)現(xiàn)4、Java語言嵌入式SQL語句的步驟

(1)Class.forName("org.postgresql.Driver")加載PostgreSQL驅(qū)動(dòng)程序。(2)使用DriverManager.getConnection(Stringurl,Stringuser,Stringpwd)建立與數(shù)據(jù)庫(kù)的連接,返回表示連接的Connection對(duì)象,url指明數(shù)據(jù)庫(kù)服務(wù)器名、端口號(hào)及數(shù)據(jù)庫(kù)名,user指明具有連接權(quán)限的用戶名,pwd是指明用戶user的口令。(3)使用Connection對(duì)象的下列方法之一創(chuàng)建查詢語句對(duì)象:

Connection.createStatement()創(chuàng)建Statement對(duì)象,靜態(tài)SQL語句查詢;

②Connection.prepareStatement(Stringsql)創(chuàng)建PreparedStatement對(duì)象,實(shí)現(xiàn)動(dòng)態(tài)SQL語句查詢;

③Connection.prepareCall(Stringsql)創(chuàng)建CallableStatement對(duì)象來調(diào)用數(shù)據(jù)庫(kù)存儲(chǔ)過程;執(zhí)行查詢

(1)Statement.execute(Stringsql)執(zhí)行各種SQL語句,返回一個(gè)boolean類型值,true表示執(zhí)行的SQL語句具備查詢結(jié)果,可通過Statement.getResultSet()方法獲??;(2)Statement.executeUpdate(Stringsql)執(zhí)行SQL中的insert/update/delete語句,返回一個(gè)int值,表示受影響的記錄的數(shù)目;(3)Statement.executeQuery(Stringsql)執(zhí)行SQL中的select語句,返回一個(gè)表示查詢結(jié)果的ResultSet對(duì)象。在Java語言操作數(shù)據(jù)庫(kù)查詢返回結(jié)果

數(shù)據(jù)庫(kù)查詢一般需要返回多條記錄,則ResultSet接口對(duì)象用于返回查詢結(jié)果集,該結(jié)果集本質(zhì)上是內(nèi)存中用于存儲(chǔ)多條記錄的游標(biāo),主要有以下幾種方法訪問訪問游標(biāo)的記錄信息:1)ResultSet.next()將游標(biāo)由當(dāng)前位置移動(dòng)到下一行;2)ResultSet.getString(StringcolumnName)獲取指定字段的String類型值;3)ResultSet.getString(int

columnIndex)獲取指定索引的String類型值;4)ResuleSet.previous(將游標(biāo)由當(dāng)前位置移動(dòng)到上一行。向SQL語句傳遞參數(shù)

如果Java宿主語言需要向SQL語句傳遞參數(shù),則使用動(dòng)態(tài)查詢prepareStatement對(duì)象,preparedStatement預(yù)編譯SQL語句,并支持批處理,執(zhí)行查詢有類似Statement對(duì)象的三種執(zhí)行方式,且執(zhí)行方法中沒有參數(shù)。1)prepareStatement.executeUpdate()執(zhí)行更新;2)prepareStatement對(duì)象使用addBatch()向批處理中加入更新語句,3)executeBatch()方法用于成批地執(zhí)行SQL語句。Java語言嵌入式SQL語句的示例packagetestConnDB;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.PreparedStatement;importjava.sql.ResultSet;public

classSQLinJava{public

static

voidmain(String[]args){Connectionconn=null;StringURL="jdbc:postgresql://localhost:5432/testDB";StringuserName="myuser";StringpassWord="sa";Stringsid[]={"14102","14103","14202","14301","14101","14201","14503"};Stringcid[]={"1205","1208","1205","1208","1201","1201","1201"};

int

score[]={90,78,89,68,86,96,83};

try{Class.forName("org.postgresql.Driver");

conn=DriverManager.getConnection(URL,userName,passWord);System.out.println("成功連接數(shù)據(jù)庫(kù)!");

StringinsertSql="INSERTINTOstu_score(sid,cid,score)VALUES(?,?,?)";StringquerySql="selectsid,cid,scorefromstu_scorewherescore>=?";PreparedStatementpsInsert=conn.prepareStatement(insertSql);//定義動(dòng)態(tài)執(zhí)行SQL語句對(duì)象PreparedStatementpsQuery=conn.prepareStatement(querySql);//定義動(dòng)態(tài)執(zhí)行SQL語句對(duì)象Java語言嵌入式SQL語句的示例(續(xù))for(int

i=0;i<sid.length;i++)

{

psInsert.setString(1,sid[i]);

psInsert.setString(2,cid[i]);

psInsert.setInt(3,score[i]);

psInsert.addBatch();//添加批處理的記錄

}

psInsert.executeBatch();//批處理執(zhí)行多條數(shù)據(jù)記錄

psQuery.setInt(1,80);ResultSetrs=psQuery.executeQuery();

while(rs.next()){//判斷是否還有下一個(gè)數(shù)據(jù)System.out.println(rs.getString("sid")+""+rs.getString("cid")+""+rs.getInt("score"));

}

psQuery.close();

psInsert.close();

conn.close();}catch(Exceptione){System.err.println(e.getClass().getName()+":"+e.getMessage());System.exit(0);

}

}}本節(jié)學(xué)習(xí)結(jié)束!6.5JavaWeb數(shù)據(jù)庫(kù)編程了解Javaweb掌握J(rèn)SP工作過程掌握Severlet工作原理掌握Mybatise訪問數(shù)據(jù)庫(kù)【本節(jié)學(xué)習(xí)目標(biāo)】JavaWeb,是用Java技術(shù)來解決相關(guān)web互聯(lián)網(wǎng)領(lǐng)域的技術(shù)總和。web包括:web服務(wù)器和web客戶端兩部分。Web服務(wù)器介紹進(jìn)行JavaWeb項(xiàng)目的開發(fā)一般需要掌握如下幾種技術(shù):HTMLCSSJavaScriptServlet技術(shù)JSP技術(shù)JavaBean技術(shù)JDBC技術(shù)XMLAJAX技術(shù)JavaWeb常用開發(fā)技術(shù)Tomcat(Apache):當(dāng)前應(yīng)用最廣的JavaWeb服務(wù)器;JBoss(Redhat紅帽):支持JavaEE,應(yīng)用比較廣;GlassFish(Oracle):Oracle開發(fā)JavaWeb服務(wù)器,應(yīng)用不是很廣;Weblogic(Oracle):Oracle開發(fā)JavaWeb服務(wù)器,支持JavaEE,適合大型項(xiàng)目;Websphere(IBM):IBM開發(fā)JavaWeb服務(wù)器,支持JavaEE,適合大型項(xiàng)目;以上幾款常用的服務(wù)器產(chǎn)品,用戶可以根據(jù)自己的需要進(jìn)行選擇。本課程選用ApacheTomcat作為JSP開發(fā)和運(yùn)行的服務(wù)器,是一款開源軟件,可作為獨(dú)立的服務(wù)器來運(yùn)行JSP和Servlets,也可以集成在ApacheWebServer中。Web服務(wù)器介紹Eclipse是Java的集成開發(fā)環(huán)境(IDE),是一個(gè)開源的、基于Java的可擴(kuò)展開發(fā)平臺(tái)。Eclipse也可以作為其它開發(fā)語言的集成開發(fā)環(huán)境,如C,C++,PHP,和Ruby等。MyEclipse企業(yè)級(jí)工作平臺(tái)(MyEclipseEnterpriseWorkbench,簡(jiǎn)稱MyEclipse)是對(duì)EclipseIDE的擴(kuò)展,利用它可以在數(shù)據(jù)庫(kù)和JavaEE的開發(fā)、發(fā)布以及應(yīng)用程序服務(wù)器的整合方面極大的提高工作效率。它是功能豐富的JavaEE集成開發(fā)環(huán)境,包括了完備的編碼、調(diào)試、測(cè)試和發(fā)布功能,完整支持HTML,Struts,JSP,CSS,Javascript,Spring,SQL,HibernateIDEA全稱IntelliJIDEA,是Java語言開發(fā)的集成環(huán)境,是JetBrains公司的產(chǎn)品;IntelliJ在業(yè)界被公認(rèn)為最好的Java開發(fā)工具之一。JavaWebIDE集成開發(fā)工具Servlet是用Java語言編寫的服務(wù)器端小程序,駐留在web服務(wù)器中,并在其中運(yùn)行,擴(kuò)展了web服務(wù)器的動(dòng)態(tài)處理功能。Servlet的特點(diǎn)移植性好,本身是一個(gè)Java類,具有跨平臺(tái)性;JavaEE平臺(tái)支持的全部JavaAPI都可用于Servlet;安全性提高,服務(wù)器崩潰的可能性減??;多個(gè)Servlet可以組織在一起,輸出可由組生成,有助于代碼復(fù)用;可以與服務(wù)器中的其它組件交互什么是Servlet?客戶機(jī)將HTTP請(qǐng)求發(fā)送給Web服務(wù)器Web服務(wù)器將該請(qǐng)求轉(zhuǎn)發(fā)給ServletServlet處理該請(qǐng)求Servlet將響應(yīng)發(fā)送給Web服務(wù)器Web服務(wù)器將響應(yīng)轉(zhuǎn)發(fā)給客戶機(jī)Servlet執(zhí)行原理Web容器提供了運(yùn)行servlet所需的環(huán)境;它負(fù)責(zé)實(shí)例化、初始化、調(diào)用服務(wù)方法并從服務(wù)中移除servlet,管理Servlet的生命周期;實(shí)現(xiàn)ServletAPI;它充當(dāng)Web服務(wù)器和Servlet之間的橋梁;將請(qǐng)求從Web服務(wù)器轉(zhuǎn)發(fā)到Servlet;將響應(yīng)從Servlet轉(zhuǎn)發(fā)到Web服務(wù)器。Web容器Servlet基本工作流程客戶機(jī)將請(qǐng)求發(fā)送到服務(wù)器;Servlet程序是由Web服務(wù)器調(diào)用,Web服務(wù)器收到客戶端的Servlet訪問請(qǐng)求后,解析客戶端的請(qǐng)求;服務(wù)器上的Web容器轉(zhuǎn)載并實(shí)例化Servlet;調(diào)用Servlet實(shí)例對(duì)象的init()方法;調(diào)用Servlet的service()方法并將請(qǐng)求和響應(yīng)對(duì)象作為參數(shù)傳遞進(jìn)去;Servlet創(chuàng)建一個(gè)響應(yīng),并將其返回到Web容器。Web容器將響應(yīng)發(fā)回客戶機(jī)。服務(wù)器關(guān)閉或Servlet空閑時(shí)間超過一定限度時(shí),調(diào)用destory()方法退出。Servlet基本工作流程(續(xù))JSP(JavaServerPages)是基于Java語言的一種Web應(yīng)用開發(fā)技術(shù)。利用這一技術(shù)可以建立安全、跨平臺(tái)、易維護(hù)的Web應(yīng)用程序。JavaServerPages一種Web服務(wù)器端的開發(fā)技術(shù)JSP≈HTML+Java什么是JSPJSP運(yùn)行原理翻譯階段編譯階段請(qǐng)求處理階段Server存儲(chǔ)的JSP文件(*.jsp)(抽象)請(qǐng)求(抽象)響應(yīng)(抽象)會(huì)話JavaServlet實(shí)現(xiàn)代碼(*.java)Java翻譯工具翻譯轉(zhuǎn)換JavaServlet實(shí)現(xiàn)類(*.class)Java編譯工具編譯JavaServlet實(shí)現(xiàn)對(duì)象JSP容器激活請(qǐng)求準(zhǔn)備請(qǐng)求響應(yīng)會(huì)話HTML標(biāo)記JSP標(biāo)記(分為指令標(biāo)記、動(dòng)作標(biāo)記)成員變量與成員方法<%!%>Java程序片<%%>Java表達(dá)式<%=%>注釋JSP頁(yè)面的組成JSP頁(yè)面的基本結(jié)構(gòu)118JSP頁(yè)面可由5種元素組合而成:①普通的HTML標(biāo)記符;②JSP標(biāo)記,如指令標(biāo)記、動(dòng)作標(biāo)記;③變量和方法的聲明;④Java程序片;⑤Java表達(dá)式;<%@pagecontentType="text/html;charset=GBK"%><%@pageimport="java.util.Date"%>

<%!

Datedate;

intsum;

publicint

getFactorSum(intn){for(int

i=1;i<n;i++){if(n%i==0)sum=sum+i;}returnsum;}%><HTML><BODYbgcolor=cyan>

<FONTsize=4><P>程序片創(chuàng)建Date對(duì)象:

<%

date=newDate();

out.println("<br>"+date+"<br>");

intm=100;

%>

<%=m%>

的因子之和是(不包括<%=m%>):

<%=getFactorSum(m)%></FONT></BODY></HTML>QQ群下載Eclipse聯(lián)機(jī)安裝文件,并安裝運(yùn)行安裝文件,選擇如右圖安裝Eclipse后運(yùn)行指定工作目錄安裝eclipsewebtools下載安裝eclipsewebtools下載安裝eclipsewebtools(續(xù))如果是從QQ群下載的apache-tomcat-9.0.2

解壓到自己規(guī)劃的Tomcat服務(wù)器目錄配置Tomcat的環(huán)境變量(1)(2)創(chuàng)建Web工程指定工程名及tomcat路徑可以默認(rèn)不添加文件夾在網(wǎng)上搜索下載合適版本的JAR包,并拷貝到右圖的目錄中在工程的WebContent目錄下創(chuàng)建WebSQL.jsp在工程的WebContent目錄下創(chuàng)建WebSQL.jsp(續(xù))選擇WebSQL.jsp->點(diǎn)擊右鍵->RunAs->RunonServer->Tomcatv9.0Server->Finish,執(zhí)行WebSQL.jsp程序選擇WebSQL.jsp->點(diǎn)擊右鍵->RunAs->RunonServer->Tomcatv9.0Server->Finish,執(zhí)行WebSQL.jsp程序在安裝Eclipse和Tomcat后,如果不是新建Web工程項(xiàng)目,而是使用原有的Web工程項(xiàng)目,如何將現(xiàn)有工程項(xiàng)目導(dǎo)入?(1)打開已有的工程項(xiàng)目(2)給Eclipse配置Tomcat服務(wù)器安裝目錄Tomcat目錄指定成功MyBatis是Apache的開源項(xiàng)目iBatis,基于Java的持久層框架,提供的持久層框架包括SQLMaps和DataAccessObjects(DAOs)。MyBatis是支持普通SQL查詢、存儲(chǔ)過程和高級(jí)映射的優(yōu)秀持久層框架。MyBatis使用簡(jiǎn)單的XML或注解用于配置和原始映射,將接口和Java的POJOs(PlainOrdinaryJavaObjects,普通的Java對(duì)象)映射成數(shù)據(jù)庫(kù)中的記錄,而不是使用JDBC代碼和參數(shù)實(shí)現(xiàn)對(duì)數(shù)據(jù)的檢索。MyBatis訪問數(shù)據(jù)庫(kù)技術(shù)Mybatis功能架構(gòu)Mybatis訪問數(shù)據(jù)庫(kù)基本步驟第一步:讀取配置文件SqlMapConfig.xml,此文件作為Mybatis的全局配置文件,配置了Mybatis的運(yùn)行環(huán)境等信息。mapper.xml文件即SQL映射文件,文件中配置了操作數(shù)據(jù)庫(kù)的SQL語句,此文件需要在SqlMapConfig.xml中加載;第二步:SqlSessionFactoryBuilder通過Configuration生成sqlSessionFactory對(duì)象。第三步:通過sqlSessionFactory打開一個(gè)數(shù)據(jù)庫(kù)會(huì)話sqlSession會(huì)話,操作數(shù)據(jù)庫(kù)需要通過sqlSession進(jìn)行。第四步:Mybatis底層自定義了Executor執(zhí)行器接口操作數(shù)據(jù)庫(kù),Executor接口負(fù)責(zé)動(dòng)態(tài)SQL的生成和查詢緩存的維護(hù),將MappedStatement對(duì)象進(jìn)行解析,SQL參數(shù)轉(zhuǎn)化、動(dòng)態(tài)SQL拼接,生成JDBCStatement對(duì)象。Mybatis訪問數(shù)據(jù)庫(kù)基本步驟(續(xù))以簡(jiǎn)單的登錄程序?yàn)槔僭O(shè)有數(shù)據(jù)庫(kù)表usertable,username列存儲(chǔ)用戶名,pasword存儲(chǔ)用戶密碼。在表中初始化一條記錄。在此采用Servlet+MyBatis的模式來實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的訪問。Mybatis訪問數(shù)據(jù)庫(kù)示例第1步:在MyBatis的官網(wǎng)下載相關(guān)jar包,并將jar和lib目錄下jar包添加到工程SQLWebDemo的WebContent->Web-INF->lib目錄。第2步:在工程SQLWebDemo的WebContent->src目錄創(chuàng)建com.test.entity包,并在包下創(chuàng)建Java文件User.java用于定義用戶類,其代碼如下:第2步:在工程SQLWebDemo的WebContent->src目錄創(chuàng)建com.test.entity包,并定義UserMapper.xml映射文件,其代碼如下:第3步:在WebContent->src->config目錄下,創(chuàng)建全局配置文件SqlMapConfig.xml第4步:在包c(diǎn)om.test.util下創(chuàng)建GetSqlSession類,在類中定義createSqlSession()方法返回會(huì)話session對(duì)象。第5步:在定義com.test.dao包下定義接口UserDao。第5步:在定義com.test.dao包下實(shí)現(xiàn)UserDao接口的類UserDaoImplement,用于判斷用戶輸入的用戶名和密碼的有效性。第6步:在包c(diǎn)om.test.Servlet下定義Servlet類LoginServlet,方法doPost(HttpServletRequest

req,HttpServletResponse

resp)用于響應(yīng)登錄頁(yè)面請(qǐng)求。第7步:配置Web.xml文件,將Servlet映射到頁(yè)面。第8步:現(xiàn)在用html實(shí)現(xiàn)簡(jiǎn)易登錄頁(yè)面程序運(yùn)行結(jié)果本節(jié)學(xué)習(xí)結(jié)束!6.6

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論