原文地址:
https://blog.csdn.net/tang_2214/article/details/80349557
PreparedStatement爲什麼能在一定程度上防止SQL注入?
PreparedStatement會對SQL進行了預編譯,在第一次執行SQL前數據庫會進行分析、編譯和優化,同時執行計劃同樣會被緩存起來,它允許數據庫做參數化查詢。在使用參數化查詢的情況下,數據庫不會將參數的內容視爲SQL執行的一部分,而是作爲一個字段的屬性值來處理,這樣就算參數中包含破環性語句(or ‘1=1’)也不會被執行。
怎麼使用PreparedStatement?如何避免SQL注入式攻擊?PreparedStatement與Statement有什麼區別,有什麼樣的優勢?
============================================================================
一個PreparedStatement簡單例子
public class JDBCTest {
public static void main(String[] args) {
//表示使用Unicode字符集;字符編碼設置爲utf-8;不使用SSL連接
String URL = "jdbc:mysql://127.0.0.1:3306/sampledb?useUnicode=true&" +
"characterEncoding=utf-8&useSSL=false";
String USER = "spring4";//用戶
String PASSWORD = "spring4";//密碼
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try {
//1.加載驅動程序到JVM
Class.forName("com.mysql.jdbc.Driver");
//2.創建數據庫連接
conn = DriverManager.getConnection(URL, USER, PASSWORD);
//3.創建Statement,實現增刪改查
String sql = "select user_id,user_name,credits from t_user where credits > ?";
st = conn.prepareStatement(sql);//這裏使用PreparedStatement
st.setInt(1, 8);
//4.向數據庫發送SQL命令
rs = st.executeQuery();
//5.使用ResultSet處理數據庫的返回結果
while (rs.next()) {
System.out.println(rs.getLong("user_id") + " "
+ rs.getString("user_name") + " "
+ rs.getString("credits"));
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
//6.關閉資源
try {
rs.close();
st.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Statement的幾種實現
Statement 對象用於將SQL語句發送到數據庫中。
Statement每次執行SQL語句,數據庫都要執行SQL語句的編譯,最好用於僅執行一次查詢並返回結果的情形
1、執行靜態SQL語句。通常通過Statement實例實現。
2、執行動態SQL語句。通常通過PreparedStatement實例實現。
3、執行數據庫存儲過程。通常通過CallableStatement實例實現。
‘#’和‘$’的區別
sql 預編譯指的是數據庫驅動在發送 sql 語句和參數給 DBMS 之前對 sql 語句進行編譯,這樣 DBMS 執行 sql 時,就不需要重新編譯。
‘#{ }’:解析爲一個 JDBC 預編譯語句(prepared statement)的參數標記符,一個‘ #{ }’ 被解析爲一個參數佔位符 ? 。
‘${ }’ 僅僅爲一個純粹的 string 替換,在動態 SQL 解析階段將會進行變量替換。在預編譯之前已經被變量替換了
‘${ }’變量的替換階段是在動態 SQL 解析階段,而’#{ }’變量的替換是在 DBMS 中。
PreparedStatement與Statement有什麼區別
1.PreparedStatement能預編譯,這條預編譯的SQL查詢語句能在將來的查詢中重用,這樣一來,它比Statement對象生成的查詢速度更快。
2.PreparedStatement可以寫動態參數化的查詢
3.PreparedStatement可以防止SQL注入式攻擊
4.PreparedStatement查詢可讀性更好,追加條件的語句很亂
5.PreparedStatement不允許一個佔位符(?)有多個值