转载请注明原文地址: http://www.cnblogs.com/ygj0930/p/5876951.html

在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命令。这样一来就省下了后面每次执行时语句的编译时间。

使用预编译分4步走:

1:定义预编译的sql语句,其中待填入的参数用  ?  占位。注意,?无关类型,不需要加分号之类。其具体数据类型在下面setXX()时决定。

2:创建预编译Statement,并把sql语句传入。此时sql语句已与此preparedStatement绑定。所以第4步执行语句时无需再把sql语句作为参数传入execute()。

3:填入具体参数。通过setXX(问号下标,数值)来为sql语句填入具体数据。注意:问号下标从1开始,setXX与数值类型有关,字符串就是setString(index,str).

4:执行预处理对象。主要有:

 boolean execute()
          在此 PreparedStatement 对象中执行 SQL 语句,该语句可以是任何种类的 SQL
语句。
 ResultSet executeQuery()

          在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的
ResultSet 对象。
 int executeUpdate()

          在此 PreparedStatement 对象中执行 SQL 语句,该语句必须是一个 SQL
数据操作语言(Data Manipulation Language,DML)语句,比如
INSERTUPDATEDELETE 语句;或者是无返回内容的 SQL
语句,比如 DDL 语句。

  注意,前面创建preparedstatement时已经把sql语句传入了,此时执行不需再把sql语句传入,这是与一般statement执行sql语句所不同之处。

比如:

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

PreparedStatement prestmt = conn.prepareStatement(sql);

  prestmt.setString(1,sno);

prestmt.executeQuery();

使用预编译的好处:

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;"

因此可以达到无账号密码亦可登录网站。

如果恶意用户要是更坏一点,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与防注入式攻击以及PreparedStatement的使用教程的更多相关文章

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

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

  2. 【JDBC】预编译SQL与防注入式攻击

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

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

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

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

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

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

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

  6. JAVA基础知识之JDBC——编程步骤及执行SQL

    JDBC编程步骤 下面以mysql数据库为例, 1.加载驱动 首先需要下载数据库的驱动jar文件,并且在eclipse包中加入到class path中去, 例如mysql的驱动文件 mysql-con ...

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

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

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

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

  9. LinQ C#防注入式攻击实例代码

    注入式攻击是Web开放项目中开发人员的第一时间要考虑的问题,下面就我的开发实例分享给大家,有用的的话就点个赞吧. 定義賬戶信息類 public class UserInfors { public st ...

随机推荐

  1. spring boot对输入的字符串进行html转码

    可以使用HtmlUtils这个类进行操作.具体的可以参考API,或者点出来看.

  2. 代码实现Android5.0的下拉刷新效果

    如图所示,实现类似与gmail的下拉刷新. 项目地址:https://github.com/stormzhang/SwipeRefreshLayoutDemo 一.在xml文件中定义 这个控件在sup ...

  3. Spring MVC+Mybatis 多数据源配置

    文章来自:https://www.jianshu.com/p/fddcc1a6b2d8 1. 继承AbstractRoutingDataSource AbstractRoutingDataSource ...

  4. [Web 前端] 解决因inline-block元素导致的空白间距和元素下沉

    cp from : https://www.jianshu.com/p/617e78a27c88 ** 前言: ** CSS 中的 display:inline-block 是笔者最为喜欢的元素之一, ...

  5. Go语言之进阶篇Socket编程

    一.Socket编程 1.什么是Socket Socket起源于Unix,而Unix基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭clo ...

  6. Hash dump神器 (转)

    在Win7 x64位下无压力测试通过. 0 / INTRO========= Quarks PwDump 是一个Win32环境下的系统授权信息导出工具,目前除此之外没有任何一款工具可以导出如此全面的信 ...

  7. Leetcode-841. 钥匙和房间

    题目 有 N 个房间,开始时你位于 0 号房间.每个房间有不同的号码:0,1,2,...,N-1,并且房间里可能有一些钥匙能使你进入下一个房间. 在形式上,对于每个房间 i 都有一个钥匙列表 room ...

  8. win7系统不能用telnet命令的两种解决方法

    电脑专业人员对telnet命令都不陌生了,Telnet当成一种通信协议,在日常工作中,经常面对网络问题的人都会用到telnet命令,因为简单有效,可以帮助更快的找出问题.要是在使用过程中碰到win7纯 ...

  9. Android -- onMeasure

    onMeasure调用次数 当Activity获取焦点的时候,它就需要绘制布局.Android框架会处理绘制过程,但这个Activity必须提供它布局树的根节点. 绘制过程是从布局的根节点开始的.这个 ...

  10. 对Attention is all you need 的理解

    https://blog.csdn.net/mijiaoxiaosan/article/details/73251443 本文参考的原始论文地址:https://arxiv.org/abs/1706. ...