數(shù)據(jù)庫(kù)實(shí)現(xiàn)了數(shù)據(jù)的持久化姑隅,但我們最終要在程序里處理數(shù)據(jù)啊,那java代碼中怎么去訪問(wèn)數(shù)據(jù)庫(kù)讀寫(xiě)數(shù)據(jù)呢倔撞?這就要用到sun公司設(shè)定的一套數(shù)據(jù)庫(kù)標(biāo)準(zhǔn)了讲仰,這套標(biāo)準(zhǔn)就是JDBC(Java Database Connectivity)。但它只是規(guī)范痪蝇,不做具體實(shí)現(xiàn)鄙陡。于是數(shù)據(jù)庫(kù)廠商又根據(jù)JDBC標(biāo)準(zhǔn),實(shí)現(xiàn)自家的驅(qū)動(dòng)Driver霹俺。如:mysql驅(qū)動(dòng)com.mysql.cj.jdbc.Driver丙唧,Oracle的驅(qū)動(dòng)oracle.jdbc.OracleDriver想际。有了這套解決方案胡本,java就可以訪問(wèn)數(shù)據(jù)庫(kù)中的數(shù)據(jù)了。
如有問(wèn)題可以觀看視頻:
https://www.bilibili.com/video/BV1Bt41137iB
Java中提倡面向接口開(kāi)發(fā),而最經(jīng)典的接口設(shè)計(jì)莫過(guò)于JDBC數(shù)據(jù)庫(kù)接口。
Connection鏈接、Statement語(yǔ)句恭取、PreparedStatement預(yù)處理語(yǔ)句柠横、CallableStatement存儲(chǔ)過(guò)程、ResultSet結(jié)果集。
調(diào)用方式有三種:
Statement語(yǔ)句、PreparedStatement預(yù)處理語(yǔ)句腹缩、CallableStatement存儲(chǔ)過(guò)程盘寡,推薦使用第二種PreparedStatement,防止SQL注入,其也是預(yù)編譯性能高。
使用步驟
導(dǎo)入jar包(豐富的工具類(lèi))
獲取和數(shù)據(jù)庫(kù)的連接(用戶(hù)名岔留、密碼)
通過(guò)程序執(zhí)行SQL
通過(guò)程序處理結(jié)果
idea 創(chuàng)建項(xiàng)目并導(dǎo)入jar包
創(chuàng)建stage2 Java工程
創(chuàng)建lib目錄进胯,拷貝驅(qū)動(dòng)objbc6-11.1.0.7.0到lib目錄下
項(xiàng)目引用這個(gè)外部jar包
入門(mén)案例
SQL注入
SQL注入的解決方案
JDBC常見(jiàn)問(wèn)題
Class.forName這句話(huà)有用沒(méi)?
Class.forName可以指定class類(lèi)路徑進(jìn)行動(dòng)態(tài)創(chuàng)建對(duì)象實(shí)例渣淳,可JDBC這句話(huà)沒(méi)有返回對(duì)象啊脾还,那寫(xiě)這句有什么作用呢?看看java.sql.Driver.class的源碼就找到真相了鄙漏,原來(lái)它用了靜態(tài)代碼塊創(chuàng)建對(duì)象。
寫(xiě)了創(chuàng)建了,那不寫(xiě)呢蝶涩?怎么不寫(xiě)也能執(zhí)行呢绿聘?
Java提供了SPI機(jī)制嗽上,用戶(hù)可以自行配置類(lèi),JDBC高版本驅(qū)動(dòng)就都引入了這個(gè)支持鲜屏。如果用戶(hù)使用了Class.forName方式就自己指定了驅(qū)動(dòng)烹看,如果未寫(xiě)這句話(huà),則Java自動(dòng)去META-INF/services/java.sql.Driver文件中找啟動(dòng)類(lèi)洛史。
驅(qū)動(dòng)版本
不同版本的mysql需要不同版本的驅(qū)動(dòng)
Mysql5.0x mysql-connector-java-5.1.32.jar
Mysql8.0x mysql-connector-java-8.0.21.jar
Driver變成了: com.mysql.cj.jdbc.Driver惯殊,中間多了cj
url必須加時(shí)區(qū)參數(shù): serverTimezone=Asia/Shanghai
url增加參數(shù):characterEncoding=utf8防止中文亂碼
SQL注入
利用sql中'單撇是字符串的結(jié)束符,or只要一個(gè)條件成立其它就不用再判斷也殖,而惡意造成sql查詢(xún)失效土思,本應(yīng)該只展示一條數(shù)據(jù)务热,結(jié)果全部展現(xiàn)。
注入后形成的SQL:
大家試想如果是一個(gè)財(cái)務(wù)表己儒,本你只能看自己的信息崎岂,結(jié)果你看了所有人的信息。結(jié)果新員工比你工資高闪湾,你說(shuō)氣人不冲甘。
SQL注入解決方案:
Statement對(duì)象換為PreparedStatement對(duì)象
PS后的結(jié)果:
利用轉(zhuǎn)義字符,屏蔽了SQL中的惡意字符途样。不僅解決了sql注入問(wèn)題江醇,使系統(tǒng)變的安全,PreparedStatement還有個(gè)極大的好處何暇,它是預(yù)編譯的語(yǔ)句陶夜,其主干部分mysql進(jìn)行預(yù)編譯后緩存,下次這部分就無(wú)需在解析裆站,只把條件拼入条辟,這樣執(zhí)行效率遠(yuǎn)高于statement每次都要編譯sql語(yǔ)句。
常見(jiàn)錯(cuò)誤
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
錯(cuò)誤原因:
1)jar沒(méi)有導(dǎo)入宏胯,沒(méi)有builder path
2)Class.forName("com.mysql.jdbc.Driver"); 字符串拼寫(xiě)錯(cuò)誤
Unknown database mydb;
錯(cuò)誤原因:
數(shù)據(jù)庫(kù)名稱(chēng)拼寫(xiě)錯(cuò)誤
Access denied for user ‘root123’@‘localhost’ (using password: YES)
錯(cuò)誤原因:
數(shù)據(jù)庫(kù)用戶(hù)名或者密碼錯(cuò)誤
Table ‘py-school-db.mydb’ doesn’t exist
錯(cuò)誤原因:
表不存在,也可能表名寫(xiě)錯(cuò)了