【21-23】Statement和PreparedStatement
2022-02-18 22:46:00
# JDBC
对比Statement和PreparedStatement
- PreparedStatement 效率比 Statement 高,因为 PreparedStatement 预编译,编译一次执行 n 次,而 Statement 编译 n 次执行 n 次
- PreparedStatement 会在编译阶段做类型检查,会更安全
- PreparedStatement 不存在 SQL 注入,而 Statement 存在
- 综上所以 PreparedStatement 使用较多
- 当业务要求 SQL注入 那么使用 Statement,拼接SQL语句,支持 SQL注入
举例利用 Statement SQL注入
- 在浏览商品,例如价格升序降序等等,利用 PreparedStatement 中的 ‘?’ 并不能注入 ‘xxx desc’,所以利用 Statement
- 以下升序或者降序输出ename和sal
- 因为用 PreparedStatement ,在 处理sql字符串时,利用setString() 会让输入的 desc 加上单引号导致 sql 语句不合法,所以利用 Statement
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73package _21_Statement和PreparedStatement;
import java.sql.*;
import java.util.Scanner;
public class 演示Statement用途 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.printf("输入asc或者desc分别表示升序或降序:");
String s = scanner.nextLine();
if (!("asc".equals(s) || "desc".equals(s))){
System.out.println("输入不合法!");
return;
}
// 执行SQL
Connection conn = null;
Statement stmt = null;
ResultSet res = null;
try {
// 1. register driver
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. get connection
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/sunlie",
"root",
"root"
);
// 3. create database operation object
stmt = conn.createStatement();
// 4. execute SQL statement
String sql = "select ename, sal from emp order by sal " + s;
res = stmt.executeQuery(sql);
// 5. process result set
while(res.next()){
System.out.println(res.getString("ename") + "\t" +
res.getString("sal"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally {
// 6. close resource
if (res != null) {
try {
res.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
PrepareStatement 完成增删改
1 | package _21_Statement和PreparedStatement; |