JDBC 核心API
Statement
Statement執(zhí)行查詢
創(chuàng)建Statement的方式:
Connection.createStatement();執(zhí)行INSERT,UPDATE和DELETE:
Statement.executeUpdate()-
執(zhí)行SELECT:
Statement.executeQuery()String sql = "select empno,ename,sal,hiredate from emp"; Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql); //對(duì)rs的處理 stmt.close();
executeQuery()方法將返回SQL語(yǔ)句執(zhí)行后的結(jié)果集
Statemeent執(zhí)行插入
String sql = "insert into emp(empno,ename,jop,sal) values(1001,'張三豐',‘Manager’ 9500)";
int flag = -1;
try{
conn = ConnectionSource.getConnection();
stmt = con.createStatement();
flag = stmt.executeUpdate(sql);
//處理結(jié)果
}catch(){
//處理異常
}
executeUpdate() 方法將返回SQL語(yǔ)句執(zhí)行后影響的記錄數(shù)
Statement執(zhí)行更改
和INSERT操作完全相同,只是SQL語(yǔ)句不同
String sql = "update emp set sal = 9900 where empno = 1001";
int flag = -1;
try{
con = ConnectionSource.getConnection();
stmt = con.createStatement();
flag = stmt.executeUpdate(sql);
//處理結(jié)果
}catch(){
//處理異常
}
PreparedStatement
PreparedStatement原理
- Statement主要用于執(zhí)行靜態(tài)SQL語(yǔ)句,即內(nèi)容固定不變的SQL語(yǔ)句
- Statement每執(zhí)行一次都要對(duì)傳入的SQL語(yǔ)句編譯一次,效率較差
- 某些情況下,SQL語(yǔ)句只是其中的參數(shù)有所不同,其余字句完全相同,適用于PreparedStatement
- 預(yù)防sql注入攻擊
- PreparedStatement是接口,繼承自Statement
- SQL語(yǔ)句提前編譯,三種常用方法execute、executeQuery和executeUpdate已被更改,不再需要參數(shù)
- PreparedStatement實(shí)例包含已事先編譯的SQL語(yǔ)句
- SQL語(yǔ)句可有一個(gè)或多個(gè)IN參數(shù)
IN參數(shù)的值在SQL語(yǔ)句創(chuàng)建時(shí)未被指定肋层。該語(yǔ)句為每個(gè)IN參數(shù)保留一個(gè)問(wèn)號(hào)(“踪央?”)作為占位符
每個(gè)問(wèn)號(hào)的值必須在該語(yǔ)句執(zhí)行之前,通過(guò)適當(dāng)?shù)膕etInt或者setString 方法提供巡蘸。 - 由于PreparedStatement對(duì)象已編譯過(guò)络拌,所以其執(zhí)行速度快于Statement對(duì)象俭驮。因此,多次執(zhí)行的SQL語(yǔ)句經(jīng)常創(chuàng)建為PreparedStatement對(duì)象,以提高效率春贸。
- 批量處理
PreparedStatement pstmt = con.prepareStatement("UPDATE emp SET job=? WHERE empno=?");
SQL語(yǔ)句已發(fā)送給數(shù)據(jù)庫(kù),并編譯號(hào)為執(zhí)行作號(hào)準(zhǔn)備
pstmt.setString(1,"Manager");
pstmt.setInt(2,1001);
對(duì)占位符進(jìn)行初始化
pstmt.executeUpdate();
執(zhí)行SQL語(yǔ)句
通過(guò)PS提升性能
- 數(shù)據(jù)庫(kù)具備緩存功能混萝,可以對(duì)statement的執(zhí)行計(jì)劃進(jìn)行緩存,以避免重復(fù)分析
- 緩存原理:
- 使用statemenet本身作為key并將執(zhí)行計(jì)劃存入與statement對(duì)應(yīng)的緩存中
- 對(duì)曾經(jīng)執(zhí)行過(guò)的statements萍恕,再運(yùn)行時(shí)執(zhí)行計(jì)劃將重用
-
舉例:
- SELECT a,b FROM t WHERE c = 1;
- 再次發(fā)送相同的statemenet時(shí)譬圣,數(shù)據(jù)庫(kù)會(huì)對(duì)先前使用過(guò)的執(zhí)行計(jì)劃進(jìn)行重用,降低開銷
-
悲勑燮骸:
- SELECT a,b FROM t WHERE c = 1;
- SELECT a,b FROM t WHERE c = 2;
被視作不同的SQL語(yǔ)句,執(zhí)行計(jì)劃不可重用
String sql = "select a,b from t where c = ?";
PrearedStatemenet ps = conn.prepareStatement(sql);
for(){
ps.setInt(1,i);
ResultSet rs = ps.executeQuery();
rs.close();
ps.close();
}
SQL Injection簡(jiǎn)介
場(chǎng)景:
String sql = "select * from t where username = '"+name+"'+and password='"+password+"';輸入?yún)?shù)后,數(shù)據(jù)庫(kù)接受到完整sql語(yǔ)句將是:
select * from t where username = 'scott' and password = 'tiger';-
如果用戶輸入的passwd參數(shù)是:a 'or' 'b' ='b,則數(shù)據(jù)庫(kù)收到的SQL語(yǔ)句將是:
select * from t where username = 'scott' and password = 'a' or 'b' = 'b';
此SQL語(yǔ)句的where條件將永遠(yuǎn)為true 此現(xiàn)象被稱作SQL注入
通過(guò)PS防止SQL Injection
- 對(duì)JDBC而言,SQL注入攻擊只對(duì)Statement有效屯蹦,對(duì)PreparedStatement無(wú)效维哈,因?yàn)镻repare