数据库JDBC——PreparedStatement和Statement的区别和使用
PreparedStatement和Statement的区别
PreparedStatement对象:预编译
的 SQL 语句对象,只编译一次,支持
批量处理,可将SQL语句装载到一起,然后一次送到数据库执行,效率极高 (addBatch()方法)防止SQL注入
Statement对象:注意:如果是
一次性操作
(增删改查),PreparedStatement的开销比Statement大
- 执行
静态
SQL 语句并返回它所生成结果的对象。 不支持
批量处理,每次执行都需编译SQL语句,效率低下- 数据库不安全(
SQL注入
)
一、PreparedStatement的批量操作
//获取连接
conn = JDBCUtils.getConnection();
String sql = "insert into user(username,password) values(?,?)";
ps = conn.prepareStatement(sql);
//批量添加五条记录
for (int i = 0; i < 5; i++) {
ps.setString(1,"菠菜饭团00"+i);
ps.setString(2,"work00"+i);
ps.addBatch();
}
//如果执行成功,counts里存的都是1
int[] counts = ps.executeBatch();
二、Statement的SQL注入演示
1.登录界面
用户名:dfhsisdfs
(瞎写的)
密码:a' or 'a' = 'a
2.后台代码示例
//获取连接
conn = JDBCUtils.getConnection();
//拼接静态SQL语句
String sql = "select * from user where username= '"+username+"' and password= '"+password+"'";
//select * from user where username= 'dfhsisdfs' and password= 'a' or 'a' = 'a'
System.out.println(sql);
statement = conn.createStatement();
rs = statement.executeQuery(sql);
//判断结果集是否有数据
while(rs.next()){
username = rs.getString("username");
password = rs.getString("password");
System.out.println(username+"---"+password);
}
//释放资源
JDBCUtils.close(rs,ps,conn);
打印的SQL语句为:select * from user where username= 'dfhsisdfs' and password= 'a' or 'a' = 'a'
这条语句的右边是个恒等式,相当于false or true,其结果为true,因此该语句总会被执行,最终获取到数据中user表中的所有信息。
总结
- PreparedStatement可通过占位符解决SQL注入问题
- PreparedStatement支持批量操作,效果高,性能卓著
- PreparedStatement代码的可读性和可维护性比Statement优异
任何时候都不要使用Statement
注
若要实现mysql的批量执行功能,需要在url 后面添加:rewriteBatchedStatements=true。
如果不添加的话addbatch() ,executeBatch() 在后台入库时并不会一次请求入库而是多次请求入库。