浅析Statement和PreparedStatement的区别
当我们使用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的区别的更多相关文章
- JDBC中的Statement和PreparedStatement的区别
JDBC中的Statement和PreparedStatement的区别
- Statement和PreparedStatement的区别; 什么是SQL注入,怎么防止SQL注入?
问题一:Statement和PreparedStatement的区别 先来说说,什么是java中的Statement:Statement是java执行数据库操作的一个重要方法,用于在已经建立数据库连接 ...
- Statement和PreparedStatement的区别; 什么是SQL注入,怎么防止SQL注入? (转)
问题一:Statement和PreparedStatement的区别 先来说说,什么是java中的Statement:Statement是java执行数据库操作的一个重要方法,用于在已经建立数据库连接 ...
- Statement与PreparedStatement的区别
Statement与PreparedStatement的区别 PreparedStatement预编译SQL语句,性能好. PreparedStatement无序拼接SQL语句,编程更简单. Pr ...
- [转] JDBC中的Statement和PreparedStatement的区别
以Oracle为例吧 Statement为一条Sql语句生成执行计划,如果要执行两条sql语句select colume from table where colume=1;select colume ...
- JDBC与Statement和PreparedStatement的区别
一.先来说说,什么是java中的Statement:Statement是java执行数据库操作的一个重要方法,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句.具体步骤: 1.首先导入 ...
- 7.秋招复习简单整理之请你讲讲 Statement 和 PreparedStatement 的区别?哪个性能更好?
Statement和PreparedStatement都是数据库用于执行SQL语句的句柄,但是PreparedStatement代表一个预编译的SQL. 以下是PreparedStatement和St ...
- statement和preparedstatement用法区别
1. PreparedStatement接口继承Statement, PreparedStatement 实例包含已编译的 SQL 语句,所以其执行速度要快于 Statement 对象. 2.作为 ...
- JDBC中的Statement 和PreparedStatement的区别?
PreparedStatement是预编译的SQL语句,效率高于Statement. PreparedStatement支持操作符,相对于Statement更加灵活. PreparedStatemen ...
随机推荐
- bzoj5406: Gift
全程膜拜 码得都要一样了.. 对于这种数列置换的可以理解成多个环,而对于一个大小为d的环把顺序弄对要做d-1次 总起来就是n-环数的次数 加上暴力30pt到手啦 假如题目没有限制,那就是第一类斯特林数 ...
- 利用JS判断当前来路域名并跳转到指定页面
某网站绑定了多个域名,默认情况下访问这些域名的时候是指向网站的首页,也就是访问不同域名时看到的页面是一样的,现在需要访问不同域名时显示不同页面. 一般情况下,可以用子站绑定域名的方法来实现,访问不同的 ...
- MYSQL初级学习笔记九:MySQL索引的使用!(视频序号:初级_51)
知识点十一:索引的使用(51) 什么是索引: 索引的定义: 在关系型数据库中,索引是一种与表有关的数据库结构,它可以使对应于表的SQL语句执行的更快.索引的作用相当于图书的目录,可以 根据目录中的页码 ...
- MVVM模式介绍
MVVM:模型-视图-视图模型(Model-View-ViewModel) 组成部分Model.View.ViewModel View:UI界面 ViewModel:它是View的抽象,负责Vie ...
- LA-3716(sort的神用)
题意: 给出两条长度均为n的NDA链A和B,找出一段最长的字串[l,r]使得该区域的突变位置不超过p%; 思路: sum[i]表示[1,i]中不相同的个数,可得表达式(sum[i]-sum[j])/( ...
- MyBatis学习 之 四、动态SQL语句
有些时候,sql语句where条件中,需要一些安全判断,例如按某一条件查询时如果传入的参数是空,此时查询出的结果很可能是空的,也许我们需要参数为空时,是查出全部的信息.使用Oracle的序列.mysq ...
- Java中断机制
1. 引言 当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制台敲入quit命令以结束某个后台服务时……都需要通过一个线程去取消另一个线程正在执行的任务.Java没有提供一种安全直接的方法 ...
- bzoj1304
树形dp 题目是要求最深的颜色 先开始觉得设dp[i][0/1/2]表示这个点的状态,然后发现没办法保证该点是最深的点,且dp状态没有实际意义,其实dp[i][0/1]表示当前i的子树颜色为c^1的叶 ...
- git只clone仓库中指定子目录
基于sparse clone变通方法 [root@vm_test backup]# mkdir devops[root@vm_test backup]# cd devops/[root@vm_test ...
- CodeForces - 55D && UVALive - 6528
A. 问L到R有多少能被自己各个数位上的非零数字整除的数字. 关键在于dp的状态:注意到这里有三个关键属性:当前数位,2~9出现的情况(0,1不用管), 原数字取余2520的结果(2~9的最小公倍数) ...