JDBC:
寶坻網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián),寶坻網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為寶坻上千余家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站建設(shè)要多少錢,請找那個售后服務(wù)好的寶坻做網(wǎng)站的公司定做!
雖然由于快節(jié)奏的開發(fā),編程速度的追求,越愛越多的MVC框架出現(xiàn),比如持久層的hibernate,
mybatis等等,他們對Dao層的支持都很強大,既快速,又簡便。但是他們的底層同樣是使用了JDBC,
為了追求高速簡便,我們可以不使用JDBC,但一定要了解JDBC。了解JDBC也有助于學(xué)習(xí)其他持久層框架。
java和數(shù)據(jù)庫交互需要中間程序作為中轉(zhuǎn)。在很早以前,數(shù)據(jù)庫廠商還沒有一套統(tǒng)一的API作為
java語言和數(shù)據(jù)庫的接口,開發(fā)程序是一件很頭疼的事。對不同的數(shù)據(jù)庫需要寫不同的程序來作為交互。
java訪問-----oracle程序-----oracle數(shù)據(jù)庫
java訪問------MySQL程序------mysql數(shù)據(jù)庫
java訪問-------db2程序--------db2數(shù)據(jù)庫
那到底什么是JDBC呢:
JDBC是代表Java數(shù)據(jù)庫連接,這對java編程語言和廣泛的數(shù)據(jù)庫之間獨立于數(shù)據(jù)庫的連接標(biāo)準(zhǔn)的Java API
有了JDBC開發(fā)就統(tǒng)一了很多。
java訪問-----JDBC程序-----oracle數(shù)據(jù)庫
java訪問------JDBC 程序------mysql數(shù)據(jù)庫
java訪問------JDBC 程序--------db2數(shù)據(jù)庫
以下簡介JDBC針對oracl和mysql數(shù)據(jù)庫。
oracle提供的jdbc接口的實現(xiàn)類-------ojdbc5.jar------jdk5.0 ojdbc6.jar-----jdk6.0
mysql提供的jdbc接口實現(xiàn)類--------mysql-connector-java-6.0.6
如果要開發(fā)JDBC程序,必然少不了這些jar包。下載可以去官網(wǎng)
https://dev.mysql.com/downloads/connector/
JDBC常用API簡介:
java.sql.Connection:代表一個數(shù)據(jù)庫連接;
java.sql.Statement:發(fā)送sql語句1至數(shù)據(jù)庫;(發(fā)送sql的工具)
DriverManager:(類) 管理多個數(shù)據(jù)庫驅(qū)動類
java.sql.ResultSet:結(jié)果集,存放查詢語句執(zhí)行后返回的數(shù)據(jù)結(jié)果
下圖1.0為JDBC訪問數(shù)據(jù)庫流程
圖1.0
JDBC開發(fā)步驟
1: 加載驅(qū)動
如果是oracle數(shù)據(jù)庫:
將oracle ojdbc.jar 復(fù)制到項目里,點擊項目,右鍵build path --add to buidpath
Class.forName("oracle.jdbc.OracleDriver");
如果是mysql數(shù)據(jù)庫:
將mysql mysql-connector-java-6.0.6-bin 復(fù)制到項目里,build path --add to buidpath
Class.forName("com.mysql.jdbc.Driver") ;
2:連接數(shù)據(jù)庫
user:root----數(shù)據(jù)庫用戶名
password:root------數(shù)據(jù)庫密碼
url: oracle ----協(xié)議 :子協(xié)議 :thin:@ip:端口:SID(SID數(shù)據(jù)庫的實例名)。
eg:String url = "jdbc:oracle:thin:@localhost:1521:XE";
url:mysql ------ 協(xié)議:子協(xié)議://ip:端口:數(shù)據(jù)庫名
eg:String url = "jdbc:mysql://localhost:3306/zdx";
3:準(zhǔn)備sql
sql字符串中不能有分號;
4:Statement將sql發(fā)送至數(shù)據(jù)庫
int i= executeUpdate(sql); //返回受影響的行數(shù)
5:如果是查詢語句,返回結(jié)果集,處理ResultSet。
6:關(guān)閉連接,釋放資源,按照先打開后關(guān)閉的原則。
以上6步驟時開發(fā)JDBC程序的標(biāo)準(zhǔn)步驟。
ResultSet結(jié)果集簡介及使用方法:
ResultSet結(jié)果集:存放查詢結(jié)果數(shù)據(jù)。
ResultSet rs = Statement.executeQuery();
rs指針初始位置在第一行數(shù)據(jù)之前
boolean rs.next(): ,
將rs的指針向下移動一位,當(dāng)前行無數(shù)據(jù)返回false,有數(shù)據(jù)返回true,并獲得查詢數(shù)據(jù)。
提供一組getXXX(int列序號或String列名)方法用于取得數(shù)據(jù)
以上是JDBC簡介,下面是JDBC例子,例子才是王道。
JDBC1.0版本------是1.0版本。后面還會有更優(yōu)秀的版本娓娓道來!
JDBC_ResultSet.java
public class JDBC_ResultSet {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1:加載驅(qū)動
//Class.forName("oracle.jdbc.OracleDriver");
Class.forName("com.mysql.jdbc.Driver");
//2:獲得數(shù)據(jù)庫連接
String user = "root";
String password = "root";
//String url = "jdbc:oracle:thin:@localhost:1521:XE";
String url = "jdbc:mysql://localhost:3306/zdx?serverTimezone=UTC";
Connection conn = DriverManager.getConnection(url,user,password);
//3:準(zhǔn)備sql
String sql = "select * from student";
//4:創(chuàng)建Statement,發(fā)送sql
Statement stm = conn.createStatement();//獲的statement對象
//5:如果是查詢,處理結(jié)果集
ResultSet rs = stm.executeQuery(sql);
while(rs.next()){
int id = rs.getInt(1);
String name = rs.getString(2);
int age = rs.getInt(3);
String phone = rs.getString(4);
System.out.println(id+"---"+name+"---"+age+"---"+phone);
}
//6:關(guān)閉連接,釋放資源,原則,先打開后關(guān)閉
stm.close();
conn.close();
}
}
到了此處,我們的JDBC1.0已經(jīng)寫完了,但是為什么說是1.0呢,因為這個版本有一個很大的漏洞。
沒錯,那就是——依賴注入問題。
===================華麗麗的分割線==============================
下面我們可以看這個例子
JDBC_Statement.java
public class JDBC_Statement {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
System.out.println("請輸入卡號");
String card_id = sc.nextLine();
System.out.println("請輸入密碼");
String pwd = sc.nextLine();
//1:加載驅(qū)動
Class.forName("com.mysql.jdbc.Driver");
//2:獲得數(shù)據(jù)庫連接
String user = "root";
String password = "root";
String url = "jdbc:mysql://localhost:3306/zdx?serverTimezone=UTC";
Connection conn = DriverManager.getConnection(url,user,password);
//3:準(zhǔn)備sql
String sql = "select * from account where card_id ="+card_id
+" and password = '"+pwd+"'";
System.out.println(sql);
//4:創(chuàng)建Statement,發(fā)送sql
Statement stm = conn.createStatement();//獲的statement對象
//5:如果是查詢,處理結(jié)果集
ResultSet rs = stm.executeQuery(sql);
if(rs.next()){
System.out.println("可以取錢了");
}else{
System.out.println("密碼賬戶不正確");
}
//6:關(guān)閉連接,釋放資源,原則,先打開后關(guān)閉
stm.close();
conn.close();
}
}
這是一個銀行取錢的例子,如代碼所寫。
數(shù)據(jù)庫有這樣一張account表,數(shù)據(jù)和字段如下:
現(xiàn)在在控制臺輸入卡號密碼,卡號密碼正確即可取錢,
錯誤即提示賬戶不正確。
現(xiàn)在控制臺輸入正確卡號密碼
然后,我輸入錯誤的卡號密碼竟然也可以取錢!輸入錯誤的卡號 “123 or 1=1 -- ”密碼 "zxc"結(jié)果如下
可見依然能訪問數(shù)據(jù)庫,這對于銀行可是致命性錯誤,密碼錯誤還可以取錢。
這就是依賴注入引起的著名錯誤。
依靠人為輸入破壞sql結(jié)構(gòu).
select * from account where id = 1001 or 1=1 -- and password = 'xxx'
這條sql里,其中--是sql里的注釋 or 1=1 永遠(yuǎn)為真并且還是or連接,
所以這條sql只執(zhí)行到 or 1=1 ,1=1又是恒等。所以跳過了密碼。
為了解決這個問題,我們就要說PreparedStatement!
PreparedStatement簡介及使用
PreparedStatement構(gòu)建動態(tài)SQL,通過PreparedStatement執(zhí)行SQL語句,解決注入***。
PreparedStatement是Statement的子接口。
通過連接創(chuàng)建PreparedStatement,創(chuàng)建時將SQL語句中發(fā)生變化的部分用占位符“?“ 代替。
功能:和statement一樣,發(fā)送sql語句。
但是執(zhí)行多個同構(gòu)sql效率高。同構(gòu)sql能省去①②③步驟。
使用步驟:
1.創(chuàng)建pstm
String sql = "select * from account where card_id = ? and password = ?"
PreparedStateement pstm = conn.prepareStatement(sql);
①驗證權(quán)限
②驗證語法
③將sql轉(zhuǎn)換內(nèi)部指令
2.綁定參數(shù)
pstm.setInt(1,值);
pstm.setString(2,值);
3.發(fā)送綁定參數(shù)至DB數(shù)據(jù)庫
pstm.executeUpdate();//曾刪改
pstm.executedQuery();//查詢
④執(zhí)行內(nèi)部指令操作數(shù)據(jù)庫
mysql內(nèi)部執(zhí)行sql步驟:
①驗證權(quán)限
②驗證語法
③將sql轉(zhuǎn)換內(nèi)部指令
④執(zhí)行內(nèi)部指令操作數(shù)據(jù)庫
使用PareparedStatement解決注入***問題后的代碼如下:
JDBC2.0版本 是2.0版本>_< 。后面還會有更優(yōu)秀的版本娓娓道來!
JDBC_PreparedStatement.java
public class JDBC_PreparedStatement {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
System.out.println("請輸入卡號");
String card_id = sc.nextLine();
System.out.println("請輸入密碼");
String pwd = sc.nextLine();
//1:加載驅(qū)動
//Class.forName("com.mysql.jdbc.Driver");
//2:獲得數(shù)據(jù)庫連接
String user = "root";
String password = "root";
String url = "jdbc:mysql://localhost:3306/zdx?serverTimezone=UTC";
Connection conn = DriverManager.getConnection(url,user,password);
//3:準(zhǔn)備sql
String sql = "select * from account where card_id =? and password =?";
PreparedStatement pstm = conn.prepareStatement(sql);
pstm.setInt(1, Integer.valueOf(card_id));
pstm.setString(2, pwd);
//5:如果是查詢,處理結(jié)果集
ResultSet rs = pstm.executeQuery();
if(rs.next()){
System.out.println("可以取錢了");
}else{
System.out.println("密碼賬戶不正確");
}
//6:關(guān)閉連接,釋放資源,原則,先打開后關(guān)閉
rs.close();
pstm.close();
conn.close();
}
}
現(xiàn)在用PreparedStatement程序執(zhí)行,輸入卡號,密碼
出現(xiàn)異常,不會再出現(xiàn)密碼錯誤卻取錢的問題了!??!
總結(jié)對比一下 Statement 和PreparedStatement
Statement | PreparedStatement | |
關(guān)系 | 父接口 | 子接口 |
安全 | 存在注入隱患 | 解決sql注入 |
效率 | 執(zhí)行異構(gòu)sql快 | 執(zhí)行同構(gòu)sql快 |
至此JDBC2.0結(jié)束。JDBC基本內(nèi)容結(jié)束,以下是JDBC進階內(nèi)容。和優(yōu)化版JDBC例子。
=====================華麗麗的分割線===========================
由于 篇幅有限,后續(xù)部分請參閱下篇博客。由淺到深學(xué)習(xí)JDBC二
不妥之處懇請讀者批評指正,共同進步。
網(wǎng)站題目:由淺到深學(xué)習(xí)JDBC一
文章出自:http://bm7419.com/article38/gihppp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、微信小程序、搜索引擎優(yōu)化、動態(tài)網(wǎng)站、做網(wǎng)站、全網(wǎng)營銷推廣
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)