在JDBC编程中,常用Statement、PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedStatement 用于执行参数化查询,而 CallableStatement则是用于存储过程。

1、Statement 
      该对象用于执行静态的 SQL 语句,并且返回执行结果。 此处的SQL语句必须是完整的,有明确的数据指示。查的是哪条记录?改的是哪条记录?都要指示清楚。
     通过调用 Connection 对象的 createStatement 方法创建该对象 
查询:ResultSet excuteQuery(String sql)——返回查询结果的封装对象ResultSet. 用next()遍历结果集,getXX()获取记录数据。
修改、删除、增加:int excuteUpdate(String sql)——返回影响的数据表记录数.

2、PreparedStatement 
    SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。 
    可以通过调用 Connection 对象的 preparedStatement() 方法获取 PreparedStatement 对象 
    PreparedStatement 对象所执行的 SQL 语句中,参数用问号(?)来表示,调用 PreparedStatement 对象的 setXXX() 方法来设置这些参数. setXXX() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值,注意用setXXX方式设置时,需要与数据库中的字段类型对应,例如mysql中字段为varchar,就需要使用setString方法,如果为Date类型,就需要使用setDate方法来设置具体sql的参数。

简单来说就是,预编译的SQL语句不是有具体数值的语句,而是用(?)来代替具体数据,然后在执行的时候再调用setXX()方法把具体的数据传入。同时,这个语句只在第一次执行的时候编译一次,然后保存在缓存中。之后执行时,只需从缓存中抽取编译过了的代码以及新传进来的具体数据,即可获得完整的sql命令。这样一来就省下了后面每次执行时语句的编译时间。

比如:

String sql="select Sname from stu where Sno=?"

PreparedStatement prestmt = conn.prepareStatement(sql);

  prestmt.setString(1,sno);

prestmt.execute();

使用预编译的好处:

1:PreparedStatement比 Statement 更快
使用 PreparedStatement 最重要的一点好处是它拥有更佳的性能优势,SQL语句会预编译在数据库系统中。执行计划同样会被缓存起来,它允许数据库做参数化查询。使用预处理语句比普通的查询更快,因为它做的工作更少(数据库对SQL语句的分析,编译,优化已经在第一次查询前完成了)。

2:PreparedStatement可以防止SQL注入式攻击

SQL 注入攻击:SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令,从而利用系统的 SQL 引擎完成恶意行为的做法。

比如:某个网站的登录验证SQL查询代码为:

1
strSQL = "SELECT * FROM users WHERE name = '" + userName + "' and pw = '"+ passWord +"';"

恶意填入:

1
2
userName = "1' OR '1'='1";
passWord = "1' OR '1'='1";

那么最终SQL语句变成了:

1
strSQL = "SELECT * FROM users WHERE name = '1' OR '1'='1' and pw = '1' OR '1'='1';"

因为WHERE条件恒为真,这就相当于执行:

1
strSQL = "SELECT * FROM users;"

因此可以达到无账号密码亦可登录网站。如果恶意用户要是更坏一点,用户填入:

1
strSQL = "SELECT * FROM users;"

SQL语句变成了:

1
strSQL = "SELECT * FROM users WHERE name = 'any_value' and pw = ''; DROP TABLE users"

这样一来,虽然没有登录,但是数据表都被删除了。

使用PreparedStatement的参数化的查询可以阻止大部分的SQL注入。在使用参数化查询的情况下,数据库系统不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行。因为对于参数化查询来说,查询SQL语句的格式是已经规定好了的,需要查的数据也设置好了,缺的只是具体的那几个数据而已。所以用户能提供的只是数据,而且只能按需提供,无法更进一步做出影响数据库的其他举动来。

参考资料:

http://www.importnew.com/5006.html

【JDBC】预编译SQL与防注入式攻击的更多相关文章

  1. JDBC编程之预编译SQL与防注入式攻击以及PreparedStatement的使用教程

      转载请注明原文地址: http://www.cnblogs.com/ygj0930/p/5876951.html 在JDBC编程中,常用Statement.PreparedStatement 和  ...

  2. JDBC编程之预编译SQL与防注入

    在JDBC编程中,常用Statement.PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedS ...

  3. jdbc预编译实现方式

    jdbc预编译可以有两种方式: 方式一.jdbc自己实现的预编译,就是做一下特殊字符处理来防SQL注入,看PreparedStatement源码就可以了. public static void mai ...

  4. hibernate预编译SQL语句中的setParameter和setParameterList

    使用预编译SQL语句和占位符參数(在jdbc中是?),可以避免由于使用字符串拼接sql语句带来的复杂性.我们先来简单的看下.使用预编译SQL语句的优点. 使用String sql = "se ...

  5. atitit.查看预编译sql问号 本质and原理and查看原生sql语句

    atitit.查看预编译sql问号 本质and原理and查看原生sql语句 1. 预编译原理. 1 2. preparedStatement 有三大优点: 1 3. How to look  gene ...

  6. mybatis中预编译sql与非预编译sql

    预编译sql有缓存作用,非预编译没得 mybaits中带有#传参的有预编译左右,$没得 多用#传参 预编译语句的优势在于归纳为:一次编译.多次运行,省去了解析优化等过程:此外预编译语句能防止sql注入 ...

  7. 为什要使用预编译SQL?(转)

    本文转自https://www.cnblogs.com/zouqin/p/5314827.html 今天在研发部技术大牛的指点下,我终于明白了为什么要使用SQL预编译的形式执行数据库JDBC:

  8. 为什要使用预编译SQL?

    今天在研发部技术大牛的指点下,我终于明白了为什么要使用SQL预编译的形式执行数据库JDBC:

  9. jdbc预编译插入数据操作

    package com.test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Prepare ...

随机推荐

  1. EF4.0和EF5.0增删改查写法区别

    1 public T AddEntity(T entity) 2 { 3 //EF4.0的写法 4 添加实体 5 //db.CreateObjectSet<T>().AddObject(e ...

  2. Android 开发问题集合

    1.屏幕横.竖切换 修改“AndroidManifest.xml”的android:screenOrientation 一般需要:landscape.portrait 2.修改应用名字 修改“Andr ...

  3. HDU 5313 Bipartite Graph (二分图着色,dp)

    题意: Soda有一个n个点m条边的二分图, 他想要通过加边使得这张图变成一个边数最多的完全二分图. 于是他想要知道他最多能够新加多少条边. 注意重边是不允许的. 思路: 先将二分图着色,将每个连通分 ...

  4. angular js 实例参数学习

    <!DOCTYPE html> <html> <head> <meta name="description" content=" ...

  5. django - 修改 request.POST的值

    # querydict改为mutable data = data.copy() data.update({'key_list': DATA_UPLOAD_PARAMETER}) 默认的request. ...

  6. Oracle日常维护脚本

    1.正常停库流程     ps -ef|grep LOCAL=NO|cut -c 9-15|xargs kill -9      shutdown immediate; 2.备份数据库     bac ...

  7. Tour

    题意: 给n个点的坐标,求形成的最短的闭合回路. 分析: 经典问题,dp[i][j]表示有1-i点再由j回到1点的最短距离,i点有两种情况,在去的路径上 dp[i][j]=min(dp[i][j],d ...

  8. Shell获取Aix/linux/unix机器上db2和os的信息并上传到指定服务器

    (之前写过一篇类似的文章,当时传输文件用的是ftp,因为项目觉得ftp不够安全所以这次换成了scp,同时对脚本的一些地方也做了一些调整) 其实做这个东西还是因为项目的需求,需要获取某些机器(目前主要是 ...

  9. <转>DNS服务系列之二:DNS区域传送漏洞的安全案例

    DNS区域传送(DNS zone transfer)指的是一台备用服务器使用来自主服务器的数据刷新自己的域(zone)数据库.这为运行中的DNS服务提供了一定的冗余度,其目的是为了防止主的域名服务器因 ...

  10. 关于display显示 linux

    export DISPLAY=ipaddressofyourmachineorpc:0.0 如果要在本来的机器上显示,使用 export DISPLAY=localhost:0