JDBC以及相關技術學習(四)----運載SQL進行查詢交通工具Statement

Statement:主要負責將SQL發送給數據庫,並將返回的結果放在ResultSet中。另外,充當同樣角色的還包括了PreparedStatement、CallableStatement,這三個類的關係是 PreparedStatement繼承Statement,而CallableStatement繼承PreparedStatement,其中,PreparedStatement相對於Statement主要會對傳遞的參數進行處理,而CallableStatement主要用於執行存儲過程。

Statment主要有以下這些常用的方法:

setMaxRows:設置ResultSet返回數據的最大限制
setMaxFieldSize:設置最大的數據塊
setEscapeProcessing可打開或關閉轉義處理;缺省狀態爲打開。
setQueryTimeout:設置查詢超時的時間,查詢超過該時間,程序就不再等待,直接報錯
cancel:取消操作
getWarnings:獲取數據庫警告
clearWarnings:清除數據庫警告
execute:執行SQL,可能反悔多個結果集
getResultSet:返回當前結果集
getUpdateCount:獲取計數器數量
getMoreResults:指針跳轉到下一個結果集或計數器
setFetchDirection:設置獲取數據的方向
setFetchSize:設置每次獲取數據數量
getResultSetConcurrency:獲取此Statement對象生成的ResultSet對象的結果集併發性
getResultSetType:獲取結果集合類型
addBatch:添加到批量處理
clearBatch:刪除批量處理
executeBatch:執行批量處理
getConnection:獲取連接
getGeneratedKeys:獲取自增主鍵
executeUpdate:執行更新語句、插入語句等沒有返回查詢結果的語句
getResultSetHoldability:獲取此Statement對象生成的ResultSet對象的結果集合可保存性
isClosed:是否關閉
setPoolable:請求將 Statement 池化或非池化。


其中,executeUpdate與executeQuery是比較常用的,分別爲執行刪除、增加更新的語句,並返回受影響的行數,而executeQuery語句主要爲執行SQL並返回結果集。

execute同樣是執行SQL語句,不過返回的可能是多個結果集,通常與getResultSet (獲取當前結果集)  getMoreResults(把指針跳轉到下一個結果集)

addBatch與executeBatch也是比較常用的語句,通常將要執行的語句先批量添加進去,然後再批量執行,這樣可以減少與數據庫的交互次數,提高程序的性能。


但是,Statement主要是通過拼湊SQL並執行,可能存在SQL注入的問題,如下面代碼:

public static void read(String name) throws SQLException{
JDBCToolSingleTon jDBCToolSingleTon = JDBCToolSingleTon.getInstance();
Connection conn = jDBCToolSingleTon.getConnection();
Statement statement = conn.createStatement();
String sql = "select id,name,birthday,account from UserInfo where name='"+name+"'";
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()){
System.out.println(resultSet.getString("name"));
}
jDBCToolSingleTon.freeResource(conn, resultSet, statement);

}


加入別人傳遞進來的參數是:‘ or '1'='1,這樣,拼湊成的SQL就變成了:select id,name,birthday,account from UserInfo where name='' or '1'='1',這樣就會導致查詢結果錯誤,當然,我們可以採用對字符串進行替換處理的情況來解決,但程序就變得不優雅了,爲了解決這個問題,就需要PreparedStatement上場了。

PreparedStatement 主要是在Statement的基礎上再進一步的封裝,可以有效解決SQL注入的問題。

PreparedStatement 繼承自Statement方法,除了Statement的方法,PreparedStatement 主要多出了一些Set的方法用於設置參數,如下:

setString

setBytes

setDate

.....等,用於設置參數,代碼如下:


public static void readNoSQLInject(String name) throws SQLException{
JDBCToolSingleTon jDBCToolSingleTon = JDBCToolSingleTon.getInstance();
Connection conn = jDBCToolSingleTon.getConnection();
String sql = "select id,name,birthday,account from UserInfo where name=?";
PreparedStatement pStatement = conn.prepareStatement(sql);
pStatement.setString(1, name);
ResultSet resultSet = pStatement.executeQuery();//注意,這裏不能加上參數,否則就是調用了Statement了

while(resultSet.next()){
System.out.println(resultSet.getString("name"));
}
jDBCToolSingleTon.freeResource(conn, resultSet, pStatement);

}

從代碼中我們可以看到,name的參數成了一個?,然後通過setString的方法對Name進行賦值,然後通過執行executeQuery進行查詢,注意,特別要注意,調用PreparedStatement的時候,一定要調用沒有參數的exeucteQuery()方法,而不能調用帶參數的executeQuery(SQL)方法,否則就是調用了其父類的方法了,達不到我們想要的目的,達得一提的是,PreparedStatement不但可以處理這些特殊字符串,還有對SQL進行預編譯的處理,可以一定程度上提高程序的性能。

CallableStatement  主要繼承自PreparedStatement,主要用於執行SQL語句,很簡單,看下代碼就懂了。


public int Create(){
Connection conn = null;
CallableStatement cs = null;
ResultSet rs = null;
try{
conn =JDBCTool.getConnection();
String sql = "  { call addUser(?,?,?,?)}";//注意是先寫大括號,然後在裏面寫call
cs = conn.prepareCall(sql);//
cs.registerOutParameter(4, Types.INTEGER);//註冊參數關鍵語句
cs.setString(1,"psname");
cs.setDate(2, new java.sql.Date(System.currentTimeMillis()));
cs.setFloat(3, 100f);
cs.executeUpdate();
int id = cs.getInt(4);
System.out.println("id="+id);

}catch(Throwable e){
e.printStackTrace();
}
finally{

}
return 0;
 

}

相對於PreparedStatement,CallableStatement 主要多了一個  registerOutParameter方法,用於註冊返回的參數。








發佈了41 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章