在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. UVa 11105 (筛法) Semi-prime H-numbers

    题意: 你现在来到了一个所有的数都模4余1的世界,也就是除了这种数没有其他的数了. 然而素数的定义依然没变,如果一个数不能写成两个非1数字的乘积,则它是素数. 比如,在这里5就变成了最小的素数. 两个 ...

  2. UVa 12063 (DP) Zeros and Ones

    题意: 找出长度为n.0和1个数相等.没有前导0且为k的倍数的二进制数的个数. 分析: 这道题要用动态规划来做. 设dp(zeros, ones, mod)为有zeros个0,ones个1,除以k的余 ...

  3. FTP出现211-Extension supported 停止的解决方法

    FTP出问题211-Extension supported 停止的解决方法 FTP出问题211-Extension supported 停止的解决方法 FLASHFXP FTP上传登录时提示Exten ...

  4. hdu 4612 Warm up(缩点+树上最长链)

    本来就是自己负责图论,结果水了= = 题目其实很裸,就是求桥的数量,只是要新加上一条边罢了.做法:先缩点.再在树上搜最长链(第一场多校的hdu 4607Park Visit就考了最长链,小样,套个马甲 ...

  5. iphone 如何清空UIWebView的缓存

      iphonecachingapplicationcookiescacheperformance I actually think it may retain cached information ...

  6. Leap Motion 开发笔记

    Leap Motion 体系架构 Leap Motion支持所有主流操作系统,leap motion在Windows系统下是作为一个服务运行的,在Mac和Linux是后台守护进程.软件通过USB线连接 ...

  7. 原创:js代码, 让dedecms支持Tag选择, 添加内容更为方便,不用手输Tag

    dedecms在编辑修改内容时,TAG标签需要手动输,中文的Tag, 中间还得用半角字符','分隔,  输入法切来切去很不方便,   于是动手改后台代码, 利用后台的tags_main.php, 让d ...

  8. Android获取SharedPreferences失败,且App无法启动

    说明: 一个app访问另外一个app的SharedPreferences,程序启动之后没有显示界面就卡死了,无任何提示信息. 错误原因: 应用调用createPackageContext失败,但是也不 ...

  9. 【转】mac终端安装node时候,显示“-bash: brew: command not found”,怎么解决?

    原文网址:https://segmentfault.com/q/1010000004221389/a-1020000004221408 mac终端安装node时候,显示“-bash: brew: co ...

  10. delphi 注册 dcc70.dll

    @echo 开始注册copy dcc70.dll %windir%\system32\regsvr32 %windir%\system32\dcc70.dll /s@echo dcc70.dll注册成 ...