在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 以及它的優點
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/163251.html
標籤:Java
上一篇:11道精選阿里和華為的面試題Java技術面試題及對應答案
下一篇:JVM類加載機制
