一、Statement对象执行的SQL语句需要与字符串变量进行连接的时候,传递特殊的字符就会导致SQL注入问题
String name = "' or 1 or '";
String sql = "select * from user where name = '" + name + "'"; // 导致SQL注入 ResultSet rs = st.executeQuery(sql);
原因在于,当sql和name连接后的字符串为 select * from user where name = '' or 1 or ''; // or旁边的不是双引号, 是两个单引号, 表示空字符串
二、解决方法: 使用PreparedStatement
String sql = "select * from user where id = ? || name = ? || age = ?"; PreparedStatement ps = conn.prepareStatement(sql); // 把SQL语句中的第一个问号替换为变量id
ps.setInt(1, id);
// 把SQL语句中的第二个问号替换为变量name
ps.setString(2, name);
// 把SQL语句中的第三个问号替换为变量age
ps.setInt(3, age);
// 注意在查询时不能带参数,否则会调用ps的父类Statement的executeQuery方法
ResultSet rs = ps.executeQuery();
三、PreparedStatement相对Statement的优点
1. PreparedStatement没有SQL注入的问题。
2. Statement会使数据库频繁编译SQL, 可能造成数据库缓冲区溢出。
3. 数据库和驱动可以对PreparedStatement进行优化(只有在相关联的数据库连接没有关闭的情况下有效).