最近在看java安全编码方面的书籍,在看到SQL注入漏洞的问题时,引发了我对Statement和PreparedStatement深入总结的欲望,废话少说,下面咱们就正式开始。

当初始的SQL查询被修改成另一个完全不同形式的查询的时候,就会出现SQL注入漏洞。执行这一被修改过的查询就可能会导致信息泄露或者数据被修改。防止SQL注入漏洞的主要方法是:净化并验证非受信输入,同时采用参数化查询的方法。

       //创建数据库连接的过程略
String sql="select * from db_user where username = " + username + "and passord = " + password;
Statement stmt = connect.createStatement();
ResultSet rs = stmt.executeQuery(sql);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

采用以上方法实现数据查询时,如果攻击者能够替代username和password中的任意字符串,它们可以使用类似下面这种方式实现SQL注入:

select * from db_user where username = '随意' and password = '' or '1' = '1';
  • 1

因为’1’=’1’肯定成立,所以可以任何通过验证.更有甚者:把[‘;drop table tb_name;]作为password传入进来,则:

select * from db_user where username = '随意' and password = '';drop table tb_name;
  • 1

有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行。而如果你使用预编译语句。你传入的任何内容就不会和原来的语句发生任何匹配的关系。(前提是数据库本身支持预编译,但上前可能没有什么服务端数据库不支持编译了,只有少数的桌面数据库,就是直接文件访问的那些)只要全使用预编译语句,你就用不着对传入的数据做任何过滤。而如果使用普通的statement,有可能要对drop,等做费尽心机的判断和过滤。

改进方法:

        //创建数据库连接的过程略
String sql="select * from db_user where username = ? and passord = ?";
PreparedStatement stmt = connect.preparedStatement();
stmt.setString(1,username);
stme.setString(2,password);
ResultSet rs = stmt.executeQuery(sql);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

通过使用PreparedStatement类的set*()方法,可以进行强类型检查。这样可以减少SQL注入漏洞。

一、分情况使用Statement和PreparedStatement对象

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

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

对于使用PreparedStatement池的情况下,当使用PreparedStatement池时, 如果一个查询很特殊, 并且不太会再次执行到, 那么可以使用Statement. 如果一个查询很少会被执行,但连接池中的Statement池可能被再次执行, 那么请使用PreparedStatement. 在不是Statement池的同样情况下, 请使用Statement.

二、PreparedStatement的Batch功能

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();
  • 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

在初始实现中, PreparedStatement被用来多次执行INSERT语句。 在这里,执行了100次INSERT操作, 共有101次网络往返。 其中,1次往返是预储statement, 另外100次往返执行每个迭代。 在改进实现中, 当在100次INSERT操作中使用addBatch()方法时, 只有两次网络往返。 1次往返是预储statement, 另一次是执行batch命令。虽然Batch命令会用到更多的数据库的CPU周期, 但是通过减少网络往返,性能得到提高。 记住, JDBC的性能最大的增进是减少JDBC驱动与数据库之间的网络通讯。

注:Oracel 10G的JDBC Driver限制最大Batch size是16383条,如果addBatch超过这个限制,那么executeBatch时就会出现“无效的批值”(Invalid Batch Value) 异常。因此在如果使用的是Oracle10G,在此bug减少前,Batch size需要控制在一定的限度。

Statement和PreparedStatement深入学习总结的更多相关文章

  1. JDBC中的Statement和PreparedStatement的区别

    JDBC中的Statement和PreparedStatement的区别  

  2. 说说Statement、PreparedStatement和CallableStatement的异同(转)

    1.Statement.PreparedStatement和CallableStatement都是接口(interface). 2.Statement继承自Wrapper.PreparedStatem ...

  3. Statement和PreparedStatement的区别; 什么是SQL注入,怎么防止SQL注入?

    问题一:Statement和PreparedStatement的区别 先来说说,什么是java中的Statement:Statement是java执行数据库操作的一个重要方法,用于在已经建立数据库连接 ...

  4. 理解 Statement 和 PreparedStatement

    java,servlet中的PreparedStatement 接口继承了Statement,并与之在两方面有所不同:有人主张,在JDBC应用中,如果你已经是稍有水平开发者,你就应该始终以Prepar ...

  5. statement和preparedstatement用法区别

    1. PreparedStatement接口继承Statement, PreparedStatement 实例包含已编译的 SQL 语句,所以其执行速度要快于 Statement 对象.   2.作为 ...

  6. Statement,PreparedStatement和CallableStatement的联系和区别

    联系: CallableStatement继承自PreparedSatement,PreparedStatement继承自Statement. 区别: 1:Statement 每次执行sql语句,数据 ...

  7. Statement和PreparedStatement的特点 MySQL数据库分页 存取大对象 批处理 获取数据库主键值

    1 Statement和PreparedStatement的特点   a)对于创建和删除表或数据库,我们可以使用executeUpdate(),该方法返回0,表示未影向表中任何记录   b)对于创建和 ...

  8. Statement和PreparedStatement的区别; 什么是SQL注入,怎么防止SQL注入? (转)

    问题一:Statement和PreparedStatement的区别 先来说说,什么是java中的Statement:Statement是java执行数据库操作的一个重要方法,用于在已经建立数据库连接 ...

  9. JDBC中的Statement和PreparedStatement的差别

    以Oracle为例吧 Statement为一条Sql语句生成运行计划, 假设要运行两条sql语句 select colume from table where colume=1; select col ...

随机推荐

  1. java STW stop the world 哈哈就是卡住了

    java  STW  stop the world 哈哈就是卡住了 学习了:http://www.jb51.net/article/125400.htm

  2. [Algorithms] Insertion sort algorithm using TypeScript

    Insertion sort is a very intuitive algorithm as humans use this pattern naturally when sorting cards ...

  3. Django打造大型企业官网(七)

    4.13.新闻列表tab栏布局完成 templates/news/index.html <div class="list-outer-group"> <ul cl ...

  4. 2015 Multi-University Training Contest 9-1007 Travelling Salesman Problem

    Problem Description Teacher Mai is in a maze with n rows and m columns. There is a non-negative numb ...

  5. Codeforces Beta Round #2 B. The least round way

    这个2B题还好~~ 题目大意: 给出一个矩阵.从左上走到右下,仅仅能往右或下走.路径中每一个格子有一个数.这些数相乘得出一个数. 求这个数末尾零最少的一条路径. 解题思路: 找出一条路径.乘积得数中素 ...

  6. TC SRM 597 DEV2

    第一次玩TC的SRM,只完成了一题,有点失落,不过还是要把每个问题都研究清楚才是我的本性,呵呵 第一题思路: 任意一个数,不断除掉2以后的剩下的数若相同则YES否则NO 第二题: 最开始判断字母个数是 ...

  7. 怎么在当前的view上获取所在的控制器(UIViewController),实现跳转

    - (UIViewController *)viewController { for (UIView* next = [self superview]; next; next = next.super ...

  8. 微软2016校园招聘在线笔试 [Recruitment]

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 A company plans to recruit some new employees. There are N ca ...

  9. 【POJ 1679】 The Unique MST

    [题目链接] 点击打开链接 [算法] 先求出图的最小生成树 枚举不在最小生成树上的边,若加入这条边,则形成了一个环,如果在环上且在最小生成树上的权值最大的边等于 这条边的权值,那么,显然最小生成树不唯 ...

  10. 10.05FZSZ Day2模拟总结

    今天的题目难度比昨天小一些,但是太菜的我还是啥也不会. 今天的出题大佬是Heaplex,他的题目中倒是出现了ZZQ,不知道是否是本人? T1.a 期望得分30,实际得分30 这道题开场发现好像有什么小 ...