当我们使用java程序来操作sql server时会使用到Statement和PreparedStatement,俩者都可以用于把sql语句从java程序中发送到指定数据库,并执行sql语句。那么如何进行一个较好的选择?

首先,我们来看俩者的区别:

Statement和PreparedStatement的区别(1)

1、直接使用Statement,驱动程序一般不会对sql语句作处理而直接交给数据库;使用PreparedStamen,形成预编译的过程,并且会对语句作字符集的转换(至少在sql server)中如此。

如此,有两个好处:对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch;另外,可以比较好地解决系统的本地化问题。

2、PreparedStatement还能有效的防止危险字符的注入,也就是sql注入的问题。(但是必须使用“对?赋值的方法”才管用)

我们用一个实例来进行演示:

PreparedStatement的使用[Sql_test2.java]

/**

* PreparedStatement使用CRUD

*、PreparedStatement可以提高执行效率(因为它有预编译的功能)

*、PreparedStatement可以防止SQL注入,但是要求用?赋值的方式才可以

*/

packagecom.sqlserver;

importjava.sql.*;

publicclass Sql_test2 {

public static void main(String[] args) {

Connection ct=null;

PreparedStatement ps=null;

ResultSet rs=null;

try {

//1、加载驱动(把需要的驱动程序加入内存)

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

//2、得到连接(指定连接到哪个数据源、数据库的用户名和密码)

ct=DriverManager.getConnection("jdbc:odbc:mytest","sa","sa");

//3、创建PreparedStatement

//PreparedStatement用处:主要用于发送SQL语句到数据库

//          ps=ct.prepareStatement("select *from dept where deptno=? and loc=?");

//          //给?赋值(可防止SQL注入漏洞问题),不要直接使用拼接的方式

//          ps.setInt(1, 20);

//          ps.setString(2, "dallas");

//          //演示:查询,显示所有的部门信息

//          //ResultSet结果集,大家可以把ResultSet理解成返回一张表行的结果集

//          rs=ps.executeQuery();

//          //循环取出

//          while(rs.next()){

//              int a=rs.getInt(1);

//              String b=rs.getString(2);

//              String c=rs.getString(3);

//              System.out.println(a+"\t"+b+"\t"+c);

//          }

//使用PreparedStetement添加一条记录

//          ps=ct.prepareStatement("insert into dept values(?,?,?)");

//          ps.setInt(1, 60);

//          ps.setString(2, "安全部");

//          ps.setString(3, "上海");

//          //执行

//          int i=ps.executeUpdate();

//          if(i==1){

//              System.out.println("添加成功");

//          }else{

//              System.out.println("添加失败");

//          }

//使用PreparedStetement修改一条记录从dept表中修改loc=上海deptno改为50

//          ps=ct.prepareStatement("update dept set deptno=? where loc='上海'");

//          ps.setInt(1, 50);

//          //执行

//          int i=ps.executeUpdate();

//          if(i==1){

//              System.out.println("修改成功");

//          }else{

//              System.out.println("修改失败");

//          }

//使用PreparedStetement删除一条记录

ps=ct.prepareStatement("delete from dept where deptno=?");

ps.setInt(1, 50);

int i=ps.executeUpdate();

if(i==1){

System.out.println("删除成功");

}else{

System.out.println("删除失败");

}

} catch (Exception e) {

e.printStackTrace();

}finally{

//关闭资源,关闭顺序先创建后关闭,后创建先关闭

try {

if(rs!=null){

rs.close();

}

if(ps!=null){

ps.close();

}

if(ct!=null){

ct.close();

}

} catch (SQLException e) {

e.printStackTrace();

}

}

}

}

此段代码比较容易理解,使用了PreparedStatement,其中对问号(?)的赋值防止了SQL的危险注入问题。

如果使用Statement,则在有时候会产生危险注入。比如,一个database中有一张表user

create table  user

{

username   varchar(30)

passwd     varchar(30)

}

insert  into user values('ywq' , 'ywqwd')

select * from user where username='ywq' and passwd='ywqwd'

通过以上语句将建立一张表,并且将数据查询显示出来。

然而问题就出现在这儿!!!当我们写成select * from user where username='ywq' and passwd='ffwd'
or 1='1'的时候,还是可以查询并且显示出数据,这就意味着前面的用户名和密码成为了虚设的,不起任何作用。如此看来,漏洞就在这儿。

当使用Statement时,ps=ct.createStatement("select *from dept where deptno='10' and loc='北京'");此语句将产生危险注入,导致系统不安全。所以我们很有必要使用PreparedStatement。

修改之后的代码如下所示:

ps=ct.prepareStatement("select * from user where username=? and passwd=?");

ps.setString(1, "ywq");

ps.setString(2, "ywqwd");

此时将正确查询到数据。当第三行改为:ps.setString(2,""ywqwd" or 1=1") 时将得不到正确结果。

总结下对问号?赋值的格式如下所示:

ps=ct.prepareStatement("insert into dept values(?,?,?)");

ps.setInt(1, 60);

ps.setString(2, "安全部");

ps.setString(3, "上海");

其中后三句分别对第一句中的?进行赋值。

此时较好的解决了危险注入的问题。

浅析Statement和PreparedStatement的区别的更多相关文章

  1. JDBC中的Statement和PreparedStatement的区别

    JDBC中的Statement和PreparedStatement的区别  

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

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

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

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

  4. Statement与PreparedStatement的区别

    Statement与PreparedStatement的区别   PreparedStatement预编译SQL语句,性能好. PreparedStatement无序拼接SQL语句,编程更简单. Pr ...

  5. [转] JDBC中的Statement和PreparedStatement的区别

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

  6. JDBC与Statement和PreparedStatement的区别

    一.先来说说,什么是java中的Statement:Statement是java执行数据库操作的一个重要方法,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句.具体步骤: 1.首先导入 ...

  7. 7.秋招复习简单整理之请你讲讲 Statement 和 PreparedStatement 的区别?哪个性能更好?

    Statement和PreparedStatement都是数据库用于执行SQL语句的句柄,但是PreparedStatement代表一个预编译的SQL. 以下是PreparedStatement和St ...

  8. statement和preparedstatement用法区别

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

  9. JDBC中的Statement 和PreparedStatement的区别?

    PreparedStatement是预编译的SQL语句,效率高于Statement. PreparedStatement支持操作符,相对于Statement更加灵活. PreparedStatemen ...

随机推荐

  1. iconfont的图文混排

    最近在使用iconfont排版,但是发现完全没法混到textarea中. 希望借助 contentEditable 解决这个问题

  2. UVA10480 Sabotage —— 最小割最大流

    题目链接:https://vjudge.net/problem/UVA-10480 题解: 实际就是求最小割集. 1.什么是网络流图的“割”?答:一个边的集合,使得网络流图删除这些边之后,点被分成两部 ...

  3. js实现网页多少秒后自动跳转到指定网址

    在网上搜了一下,关于这个技术处理有多种方法,我只记下我在视频里学到的三种: 1.用一个response.sendRedirect("目标页面.jsp\.htm");实现直接跳转: ...

  4. kafka 查询 SQL Query

    . SELECT COUNT(*) FROM wiseweb_crawler_foreignmedias WHERE site_id= AND (gathertime BETWEEN '2017-05 ...

  5. 深入浅出Oracle学习笔记:Buffer Cache 和Shared pool

    Buffer cache 和 share pool 是sga中最重要最复杂的部分. 一.Buffer Cache 通常数据的读取.修改都是通过buffer cache 来完成的.buffer cach ...

  6. Python小练习_将数据库中表数据存到redis里

    # ##练习:将xxx数据库中my_user表中数据存到redis里面# 分析: pymysql.json.redis# 1.连接数据库,查到数据库里面所有的数据,游标类型要用pymysql.curs ...

  7. 【NOIP2017 DAY1T2】 时间复杂度

    [题目链接] 点击打开链接 [算法] 其实这就是一道模拟题啦! 在判error和计算时间复杂度时,我们需要用栈这种数据结构 [代码] 这题的代码还是有些难写的,写的时候一定要有条理! #include ...

  8. Android应用开发完全退出程序的通用方法

    在开发一个android应用时,有可能有N个Activity,而在每个Activity里的菜单里有个"退出程序"菜单,这里就要完全退出程序了,所以今天给大家分享的是Android应 ...

  9. 【iOS】KVC 和 KVO 的使用场景

    http://blog.csdn.net/chenglibin1988/article/details/38259865   Key Value Coding Key Value Coding是coc ...

  10. ASP.NET Core 依赖注入(DI)

    ASP.NET Core的底层设计支持和使用依赖注入.ASP.NET Core 应用程序可以利用内置的框架服务将服务注入到启动类的方法中,并且应用程序服务也可以配置注入.由ASP.NET Core 提 ...