在JDBC中使用預編譯PreparedStatement 以及它的優點 步驟 1 : 使用PreparedStatement 和 Statement一樣,PreparedStatement也是用來執行sql語句的 與創建Statement不同的是,需要根據sql語句創建PreparedStateme ...
在JDBC中使用預編譯PreparedStatement 以及它的優點
步驟 1 : 使用PreparedStatement
和 Statement一樣,PreparedStatement也是用來執行sql語句的
與創建Statement不同的是,需要根據sql語句創建PreparedStatement
除此之外,還能夠通過設置參數,指定相應的值,而不是Statement那樣使用字元串拼接
註: 這是JAVA里唯二的基1的地方,另一個是查詢語句中的ResultSet也是基1的。
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestJDBC {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String sql = "insert into hero values(null,?,?,?)";
try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
// 根據sql語句創建PreparedStatement
PreparedStatement ps = c.prepareStatement(sql);
) {
// 設置參數
ps.setString(1, "提莫");
ps.setFloat(2, 313.0f);
ps.setInt(3, 50);
// 執行
ps.execute();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
步驟 2 : PreparedStatement的優點1-參數設置
Statement 需要進行字元串拼接,可讀性和維護性比較差
String sql = "insert into hero values(null,"+"'提莫'"+","+313.0f+","+50+")";
PreparedStatement 使用參數設置,可讀性好,不易犯錯
String sql = "insert into hero values(null,?,?,?)";
.
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String sql = "insert into hero values(null,?,?,?)";
try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
Statement s = c.createStatement();
PreparedStatement ps = c.prepareStatement(sql);
) {
// Statement需要進行字元串拼接,可讀性和維修性比較差
String sql0 = "insert into hero values(null," + "'提莫'" + "," + 313.0f + "," + 50 + ")";
s.execute(sql0);
// PreparedStatement 使用參數設置,可讀性好,不易犯錯
// "insert into hero values(null,?,?,?)";
ps.setString(1, "提莫");
ps.setFloat(2, 313.0f);
ps.setInt(3, 50);
ps.execute();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
步驟 3 : PreparedStatement的優點2-性能表現
PreparedStatement有預編譯機制,性能比Statement更快
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String sql = "insert into hero values(null,?,?,?)";
try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
Statement s = c.createStatement();
PreparedStatement ps = c.prepareStatement(sql);
) {
// Statement執行10次,需要10次把SQL語句傳輸到資料庫端
// 資料庫要對每一次來的SQL語句進行編譯處理
for (int i = 0; i < 10; i++) {
String sql0 = "insert into hero values(null," + "'提莫'" + ","
+ 313.0f + "," + 50 + ")";
s.execute(sql0);
}
s.close();
// PreparedStatement 執行10次,只需要1次把SQL語句傳輸到資料庫端
// 資料庫對帶?的SQL進行預編譯
// 每次執行,只需要傳輸參數到資料庫端
// 1. 網路傳輸量比Statement更小
// 2. 資料庫不需要再進行編譯,響應更快
for (int i = 0; i < 10; i++) {
ps.setString(1, "提莫");
ps.setFloat(2, 313.0f);
ps.setInt(3, 50);
ps.execute();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
步驟 4 : PreparedStatement的優點3-防止SQL註入式攻擊
假設name是用戶提交來的數據
String name = "'蓋倫' OR 1=1";
使用Statement就需要進行字元串拼接
拼接出來的語句是:
select * from hero where name = '蓋倫' OR 1=1
因為有OR 1=1,這是恆成立的
那麼就會把所有的英雄都查出來,而不只是蓋倫
如果Hero表裡的數據是海量的,比如幾百萬條,把這個表裡的數據全部查出來
會讓資料庫負載變高,CPU100%,記憶體消耗光,響應變得極其緩慢
而PreparedStatement使用的是參數設置,就不會有這個問題
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String sql = "select * from hero where name = ?";
try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
Statement s = c.createStatement();
PreparedStatement ps = c.prepareStatement(sql);
) {
// 假設name是用戶提交來的數據
String name = "'蓋倫' OR 1=1";
String sql0 = "select * from hero where name = " + name;
// 拼接出來的SQL語句就是
// select * from hero where name = '蓋倫' OR 1=1
// 因為有OR 1=1,所以恆成立
// 那麼就會把所有的英雄都查出來,而不只是蓋倫
// 如果Hero表裡的數據是海量的,比如幾百萬條,把這個表裡的數據全部查出來
// 會讓資料庫負載變高,CPU100%,記憶體消耗光,響應變得極其緩慢
System.out.println(sql0);
ResultSet rs0 = s.executeQuery(sql0);
while (rs0.next()) {
String heroName = rs0.getString("name");
System.out.println(heroName);
}
s.execute(sql0);
// 使用預編譯Statement就可以杜絕SQL註入
ps.setString(1, name);
ResultSet rs = ps.executeQuery();
// 查不出數據出來
while (rs.next()) {
String heroName = rs.getString("name");
System.out.println(heroName);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
更多內容,點擊瞭解: 在JDBC中使用預編譯PreparedStatement 以及它的優點