Java--Statement和PrepareStatement的区别

一、语法

两者的语法区别

1、Statement语法

Statement stmt = connect.createStatement();
String sql= "SELECT * FROM cg_user WHERE userId=10086 AND name LIKE 'xiaoming'";
ResultSet rs = stmt.executeUpdate(sql);

2、PrepareStatement 

PreparedStatement preparedStatement = connect.prepareStatement("SELECT * FROM cg_user WHERE userId= ? AND name LIKE ?");  
preparedStatement .setInt(1, 10086 );  
preparedStatement .setString(2, "xiaoming");  
preparedStatement .executeUpdate();  

二、访问数据库的速度

prepareStatement会先初始化SQL,先把这个SQL提交到数据库中进行预处理,多次使用可提高效率。

createStatement不会初始化,没有预处理,没次都是从0开始执行SQL

PreparedStatement对象不仅包含了SQL语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句,而不必先编译。当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,当然也加快了访问数据库的速度。

这种转换也给你带来很大的便利,不必重复SQL语句的句法,而只需更改其中变量的值,便可重新执行SQL语句。选择PreparedStatement对象与否,在于相同句法的SQL语句是否执行了多次,而且两次之间的差别仅仅是变量的不同。如果仅仅执行了一次的话,它应该和普通的对象毫无差异,体现不出它预编译的优越性。

三、prepareStatement批量执行:

好处:Update大量的数据时, 先构建一个INSERT语句再多次的执行, 会导致很多次的网络连接.。要减少JDBC的调用次数改善性能, 可以使用PreparedStatement的AddBatch()方法一次性发送多个查询给数据库。

// 初始实现:
PreparedStatement ps = conn.prepareStatement(
                "INSERT into db_user values (?, ?, ?)");
        for (n = 0; n < 100; n++) {
            ps.setString(name[n]);
            ps.setLong(id[n]);
            ps.setInt(salary[n]);
            ps.executeUpdate();
        }
//改进实现:
//使用Batch功能
        PreparedStatement ps = conn.prepareStatement(
                "INSERT into db_user values (?, ?, ?)");
        for (n = 0; n < 100; n++) {
            ps.setString(username[n]);
            ps.setString(password[n]);
            ps.addBatch();
        }
        ps.executeBatch();

四、SQL注入漏洞:

Statement stmt = connect.createStatement();
String sql= "SELECT * FROM cg_user WHERE userId"+ userId +" AND name LIKE " + name";
ResultSet rs = stmt.executeUpdate(sql);

假如入参name的值为 or '1' = '1' 那么SQL是成立的,就会返回所有数据,或者变成这个[‘;drop table cg_user ;],那么SQL拼接后就变成:

SELECT * FROM cg_user WHERE userId='' AND name LIKE '' ; drop table cg_user ;

如果使用prepareStatement预编译就不会了,因为SQL语句在程序运行前已经进行了预编译,在程序运行时第一次操作数据库之前,SQL语句已经被数据库分析和编译,对应的执行计划也会缓存下来,之后数据库就会以参数化的形式进行查询。set值永远是把占位符当成data处理。

PreparedStatement preparedStatement = connect.prepareStatement("SELECT * FROM cg_user WHERE userId= ? AND name LIKE ?");  
preparedStatement .setInt(1, '');  
preparedStatement .setString(2, "; drop table cg_user");  
preparedStatement .executeUpdate();  

sql会变成:

SELECT * FROM cg_user WHERE userId='' AND name LIKE '; drop table cg_user'  ;

总结:

1、JDBC驱动的最佳化是基于使用的是什么功能. 选择PreparedStatement还是Statement取决于你要怎么使用它们. 对于只执行一次的SQL语句选择Statement是最好的. 相反, 如果SQL语句被多次执行选用PreparedStatement是最好的

2、PreparedStatement的第一次执行消耗是很高的. 它的性能体现在后面的重复执行. 使用PreparedStatement的方式来执行一个针对数据库表的查询. JDBC驱动会发送一个网络请求到数据解析和优化这个查询. 而执行时会产生另一个网络请求. 在JDBC驱动中,减少网络通讯是最终的目的. 如果我的程序在运行期间只需要一次请求, 那么就使用Statement. 对于Statement, 同一个查询只会产生一次网络到数据库的通讯.

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值