Java Web開發(fā)實(shí)戰(zhàn)—JDBC基礎(chǔ)—JDBC開發(fā)及基本操作
時間:2023-05-24 16:36:01 | 來源:網(wǎng)站運(yùn)營
時間:2023-05-24 16:36:01 來源:網(wǎng)站運(yùn)營
Java Web開發(fā)實(shí)戰(zhàn)—JDBC基礎(chǔ)—JDBC開發(fā)及基本操作:
上一篇學(xué)習(xí)了JDBC入門(Java Web開發(fā)實(shí)戰(zhàn)—JDBC基礎(chǔ)—JDBC入門),本篇繼續(xù)學(xué)習(xí)
JDBC開發(fā)及基本操作。JDBC開發(fā)JDBC程序的開發(fā)步驟編寫一個JDBC程序需要完成六個步驟,具體如下。
l 加載并注冊數(shù)據(jù)庫驅(qū)動(Driver類)
l 獲取數(shù)據(jù)庫連接(Connection對象)
l 獲取SQL語句執(zhí)行者(Statement對象)
l 執(zhí)行SQL語句
l 操作結(jié)果集(ResultSet對象)
l 回收數(shù)據(jù)庫資源
編寫JDBC程序的每個步驟都離不開JDBC相關(guān)API的支持,下面將對編寫JDBC程序的具體步驟進(jìn)行詳細(xì)的講解。
加載并注冊數(shù)據(jù)庫驅(qū)動JDBC定義了驅(qū)動接口java.sql.Driver,MySQL數(shù)據(jù)庫的驅(qū)動包為接口java.sql.Driver提供了實(shí)現(xiàn)類com.mysql.jdbc.Driver。在實(shí)際的開發(fā)過程中,一般采用Class類的forName方法加載驅(qū)動類,具體實(shí)現(xiàn)代碼如下。
類加載時,將執(zhí)行被加載類的靜態(tài)代碼塊,而com.mysql.jdbc.Driver類有一個靜態(tài)代碼塊,具體如下。
因此,Driver類在加載過程中即完成了對驅(qū)動的注冊。
獲取數(shù)據(jù)庫連接DriverManager類是驅(qū)動管理類,管理一組JDBC驅(qū)動程序,它通過屬性drivers存入很多驅(qū)動類。當(dāng)DriverManager獲取連接的時候,它會把drivers里的各個驅(qū)動的URL和創(chuàng)建連接時傳進(jìn)來的URL逐一比較,遇到對應(yīng)的URL,則會嘗試建立連接。通過DriverManager類獲取連接(Connection對象)的具體實(shí)現(xiàn)代碼如下。
從上述代碼片段可以看出,DriverManager類的getConnection()方法共有三個參數(shù),它們分別表示數(shù)據(jù)庫URL、登錄數(shù)據(jù)庫的用戶名和密碼,如果三者均匹配成功,就可獲取數(shù)據(jù)庫連接,為JDBC實(shí)現(xiàn)對數(shù)據(jù)庫的操作奠定基礎(chǔ)。
獲取SQL語句執(zhí)行者Connection對象提供了三種獲取SQL語句執(zhí)行者(Statement對象)的方法,其中,調(diào)用createStatement()方法獲取Statement對象,調(diào)用prepareStatement()方法獲取PreparedSatement對象,調(diào)用prepareCall()方法獲取CallableStatement對象,以獲取Statement對象為例,具體實(shí)現(xiàn)代碼如下。
如果獲取PreparedStatement對象和CallableStatement對象,還需傳入String類型的SQL語句作為參數(shù)。
執(zhí)行SQL語句并操作結(jié)果集Statement對象提供了三種方法執(zhí)行SQL語句,其中,execute()方法可以執(zhí)行任何SQL語句;executeUpdate()方法用于執(zhí)行DDL語句和DML語句,執(zhí)行DDL語句時,返回值為0,執(zhí)行DML語句時,返回值為影響的行數(shù);executeQuery()方法用于執(zhí)行實(shí)現(xiàn)查詢功能的SQL語句,返回值是一個結(jié)果集(ResultSet對象)。
以executeQuery()方法為例,具體實(shí)現(xiàn)代碼如下。
結(jié)果集(ResultSet對象)封裝了執(zhí)行查詢SQL語句后返回的結(jié)果,程序可以通過遍歷結(jié)果集獲取每一行的數(shù)據(jù)。ResultSet對象具有指向其當(dāng)前數(shù)據(jù)行的指針,在最開始的時候指針被置于第一行之前,可調(diào)用ResultSet接口的next()方法將指針移動到下一行,在實(shí)際應(yīng)用中常將ResultSet接口的next()方法放在while()循環(huán)當(dāng)中,如果有下一行,則返回True,遍歷繼續(xù)進(jìn)行,如果沒有下一行,則返回False,遍歷結(jié)束。
從結(jié)果集中獲取數(shù)據(jù)分為兩個步驟,首先調(diào)用next()、previous()、first()、last()等方法移動指針,其次調(diào)用getXxx()方法獲取指針指向行的特定列的值。該方法既可以使用列索引作為參數(shù),也可以使用列名稱作為參數(shù)。使用列索引作為參數(shù)的性能更好,使用列名稱作為參數(shù)的可讀性更好,操作結(jié)果集的具體實(shí)現(xiàn)代碼如下。
其中,參數(shù)“1”表示獲取當(dāng)前指針指向行的第一列的數(shù)據(jù),除此之外,getObject()方法的參數(shù)名稱也可以是String類型的數(shù)據(jù)表的列名,此時getObject()方法獲取該列名對應(yīng)的數(shù)據(jù)。
回收數(shù)據(jù)庫資源為了節(jié)省資源,提升性能,包括 Connection、Statement、ResultSet在內(nèi)的JDBC資源在使用之后要及時關(guān)閉。正確的關(guān)閉順序是:先得到的后關(guān)閉,后得到的先關(guān)閉。回收數(shù)據(jù)庫資源的具體實(shí)現(xiàn)代碼如下。
編寫一個JDBC程序前面講解了編寫JDBC程序的具體步驟,接下來通過一個實(shí)例來演示JDBC程序的具體實(shí)現(xiàn)。
(1)在MySQL中創(chuàng)建數(shù)據(jù)庫chapter01和數(shù)據(jù)表student,SQL語句如下。
(2)向數(shù)據(jù)表student添加數(shù)據(jù),SQL語句如下。
(3)通過SQL語句測試數(shù)據(jù)是否添加成功,執(zhí)行結(jié)果如下。
從以上執(zhí)行結(jié)果可以看出,數(shù)據(jù)添加成功。
(4)在Eclipse中新建Java工程chapter01,在工程chapter01下新建目錄lib,將MySQL數(shù)據(jù)庫的驅(qū)動jar包mysql-connector-java-5.1.37-bin.jar復(fù)制到lib目錄下,右擊lib目錄下的mysql-connector-java-5.1.37-bin.jar,在彈出的菜單中選擇Build Path→Add to Build Path,完成jar包的導(dǎo)入。在工程chapter01的src目錄下新建com.qfedu.jdbc包。
在工程chapter01的src目錄下新建com.qfedu.jdbc包,在該包下新建類TestJDBC01。
PreparedStatement對象的使用SQL注入SQL注入是比較常見的網(wǎng)絡(luò)攻擊方式,它利用現(xiàn)有程序的漏洞,將惡意的SQL命令注入到后臺數(shù)據(jù)庫,最終達(dá)到欺騙服務(wù)器并執(zhí)行攻擊者的意圖的目的。在程序的運(yùn)行過程中,SQL注入會造成數(shù)據(jù)庫信息泄露、網(wǎng)頁篡改、網(wǎng)站被掛木馬等問題。
接下來,將通過一個簡單的實(shí)例來說明SQL注入發(fā)生的過程。如果在某個系統(tǒng)的登錄模塊有如下一個驗(yàn)證權(quán)限的SQL語句。
正常情況下,用戶需要輸入正確的登錄名和密碼才能完成登錄。但是,用戶如果把輸入的密碼改為“12345 or 1=1 ”,那么真正執(zhí)行的SQL語句變?yōu)椋?br>
此時,上述查詢已基本失效,無論密碼對錯,用戶均可以成功登錄,使得程序存在重大的安全隱患,這就是SQL注入的一個具體場景。
前文中已經(jīng)介紹過,Statement對象可以通過三種方法向數(shù)據(jù)庫發(fā)送SQL語句,而這三種方法均是通過傳遞字符串類型的SQL語句作為參數(shù)來實(shí)現(xiàn)的,由此可見,使用statement類會存在SQL注入的問題。
PreparedStatement與Statement對比PreparedStatement是用來執(zhí)行SQL查詢語句的API之一,主要用于執(zhí)行參數(shù)化的操作。PreparedStatment對象可以對SQL語句進(jìn)行預(yù)編譯,這可以有效地避免SQL注入引發(fā)的問題,同時也提升了代碼的可維護(hù)性和可讀性。
與Statement對比,PreparedStatement具有以下優(yōu)點(diǎn)。
1. PreparedStatement能夠執(zhí)行參數(shù)化的SQL語句由于PreparedStatement能夠執(zhí)行帶參數(shù)的SQL語句,因此開發(fā)人員可以通過修改參數(shù)來反復(fù)調(diào)用同一SQL語句,這樣可以避免反復(fù)書寫相同SQL語句的煩瑣。
參數(shù)化的SQL語句,具體如下。
其中,“?”是參數(shù)的占位符,程序可以通過傳入不同的sid值完成參數(shù)化查詢。
2. PreparedStatement比 Statement效率更高使用PreparedStatement時,數(shù)據(jù)庫系統(tǒng)會對sql語句進(jìn)行預(yù)編譯處理,執(zhí)行計(jì)劃同樣會被緩存起來,這條預(yù)編譯的SQL語句能在將來的查詢中重用,這樣一來,它比Statement對象生成的查詢速度更快,性能更好。為了減少數(shù)據(jù)庫的負(fù)載,實(shí)際開發(fā)中一般使用PreparedStatement。
3. PreparedStatement可以防止SQL注入攻擊使用PreparedStatement的參數(shù)化的操作可以阻止大部分的SQL注入。在使用參數(shù)化查詢的情況下,數(shù)據(jù)庫系統(tǒng)不會將參數(shù)的內(nèi)容視為SQL指令的一部分來處理,而是在數(shù)據(jù)庫完成SQL指令的編譯后,才套用參數(shù)執(zhí)行。
使用PreparedStatement對象操作數(shù)據(jù)庫PreparedStatement對象通過executeUpdate()方法實(shí)現(xiàn)對數(shù)據(jù)庫的寫入,通過executeQuery()方法實(shí)現(xiàn)對數(shù)據(jù)庫的查詢。使用PreparedStatement對象操作數(shù)據(jù)庫的步驟與使用Statement對象類似,具體如下所示。
l 加載并注冊數(shù)據(jù)庫驅(qū)動(Driver類)。
l 獲取數(shù)據(jù)庫連接(Connection對象)。
l 書寫要執(zhí)行的SQL語句,其中,操作的數(shù)據(jù)用占位符“?”表示。
l 獲取SQL語句執(zhí)行者(PreparedStatement對象)。
l 為SQL語句中的參數(shù)賦值。
l 執(zhí)行SQL語句。
l 操作結(jié)果集(ResultSet對象)。
l 回收數(shù)據(jù)庫資源。
使用PreparedStatement對象實(shí)現(xiàn)批量處理在實(shí)際的項(xiàng)目開發(fā)中,有時需要向數(shù)據(jù)庫發(fā)送多條語句相同、但參數(shù)不同的SQL語句,這時需重復(fù)寫上很多條SQL語句,具體如下。
為了避免重復(fù)發(fā)送相同的SQL語句,提升執(zhí)行效率,在實(shí)際開發(fā)中常采用PreparedStatement對象的批處理機(jī)制。
JDBC基本操作為了幫助大家熟練應(yīng)用JDBC編程,接下來,本節(jié)將通過一個綜合案例來講解JDBC的基本操作,確保大家能夠深刻理解JDBC的增、刪、改、查,并能靈活地利用JDBC完成對數(shù)據(jù)庫的各項(xiàng)操作。
1. 創(chuàng)建一個Java類Student在工程chapter01下創(chuàng)建com.qfedu.jdbc.domain包,并在該包下創(chuàng)建用于保存學(xué)生數(shù)據(jù)的類Student,具體代碼如例1.4所示。
2. 創(chuàng)建JDBCUtils工具類在開發(fā)過程中,每次對數(shù)據(jù)庫的操作都需要注冊驅(qū)動、獲取連接、關(guān)閉資源等,這樣會造成大量的重復(fù)代碼。為了降低冗余,提升開發(fā)效率,一般將JDBC的相關(guān)操作封裝到JDBC工具類中。在src目錄下新建com.qfedu.jdbc.utils包,并在該包下創(chuàng)建JDBCUtils工具類,具體代碼如例1.5所示。
3. 新建StudentDao類在src目錄下新建com.qfedu.jdbc.dao包,并在該包下新建StudentDao類,該類提供對數(shù)據(jù)庫表的增加、修改、刪除、查詢等操作,具體代碼如例1.6所示。
4. 編寫測試類TestInsert在src目錄下新建com.qfedu.jdbc.test包,并在該包下新建TestInsert類,該類用于測試向表中添加數(shù)據(jù)的操作,具體代碼如例1.7所示。
5. 編寫測試類TestUpdate在src目錄下的com.qfedu.jdbc.test包下新建TestUpdate類,該類用于測試更新表中數(shù)據(jù)的操作,具體代碼如例1.8所示。
6. 編寫測試類TestDelete在src目錄下的com.qfedu.jdbc.test包下新建TestDelete類,該類用于測試刪除表中數(shù)據(jù)的操作,具體代碼如例1.9所示。
7. 編寫測試類TestSelectOne在src目錄下的com.qfedu.jdbc.test包下新建TestSelectOne類,該類用于測試查詢表中單條數(shù)據(jù)的操作,具體代碼如例1-10所示。
8. 編寫測試類TestSelectAll在src目錄下的com.qfedu.jdbc.test包下新建TestSelectAll類,該類用于測試查詢表中所有數(shù)據(jù)的操作。
小結(jié):Java Web開發(fā)實(shí)戰(zhàn)—JDBC基礎(chǔ)https://www.zhihu.com/video/1568238629100654592主要介紹了JDBC的基本知識,包括JDBC的概念、體系結(jié)構(gòu)以及核心API,通過操作案例對知識點(diǎn)進(jìn)行鞏固和串聯(lián),通過對內(nèi)容的學(xué)習(xí),大家應(yīng)該了解JDBC的概念,掌握J(rèn)DBC的開發(fā)流程并可以開發(fā)簡單的JDBC程序。
關(guān)鍵詞:操作,基本,實(shí)戰(zhàn),基礎(chǔ)