听说都放弃 Statement 而使用 PreparedStatement 去了?
作者:互联网
目录尽量避免使用 Statement,改用PreparedStatement 来执行SQL语句。。。。。。
一、PreparedStatement和Statement的联系和区别
- 联系:PreparedStatement是Statement的子接口,为了满足Statement一些没有的的功能,特意提供的,拥有Statement的所有方法,比如:execute()、executeUpdate()、executeQuery()方法
- 区别:PreparedStatement执行SQL语句时,会将语句预编译,存储在PreparedStatement对象中,在执行相同的语句时,可以直接执行,不用多次编译,效率更高,而且,还可以使用"?"这个占位符,当大量数据有相同的列时,就不用每次都编译输入SQL语句,用法如下:
-- 向student表添加数据,例如(null,"长歌","学习")
insert into student value(null,?,?);
二、执行效率对比
分别使用Statement和PreparedStatement向数据库插入100条数据,进行所用时间的比较,为了简洁,关于数据库的连接就不细说了,不会的可以看看我前面写的 JDBC:Java连接数据库
记得先导包和写配置文件:
完整代码如下:
package cn.changge.demo01;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.Properties;
/**
* @author 长歌
* @2020年4月18日下午10:06:16
*/
public class PreparedStatementTest {
private String driver;
private String url;
private String user;
private String password;
/** 封装加载方法 **/
public void loadFile(String file) throws Exception{
//使用Properties类来加载属性文件
Properties prop = new Properties();
//通过FileInputStream,将file传入
prop.load(new FileInputStream(file));
driver = prop.getProperty("driver");
url = prop.getProperty("url");
user = prop.getProperty("user");
password = prop.getProperty("password");
//加载数据库驱动
Class.forName(driver);
}
/** 使用Statement插入200条数据 **/
public void StatementInsert() throws Exception{
//获得数据库的连接
Connection con = DriverManager.getConnection(url, user, password);
long start = System.currentTimeMillis();//开始时间
//得到Statement对象
Statement stmt = con.createStatement();
//循环插入200条数据
for(int i = 0; i<=100; i++){
stmt.executeUpdate("insert into demo value('"+ i +"')");
}
System.out.println("使用Statement用时:" + (System.currentTimeMillis()-start));
}
/** 使用PreparedStatement插入200条数据 **/
public void PreparedStatementInsert() throws Exception{
Connection con = DriverManager.getConnection(url, user, password);
long start = System.currentTimeMillis();//开始时间
//得到Statement对象
PreparedStatement pstmt = con.prepareStatement("insert into demo value(?)");
//循环插入200条数据
for(int i = 101; i<=200; i++){
pstmt.setString(1, "i");//表示第一个占位符?的值为 i (也可以有多个?)
}
System.out.println("使用PreparedStatement用时:" + (System.currentTimeMillis()-start));
}
public static void main(String[] args) throws Exception {
PreparedStatementTest pstmtt = new PreparedStatementTest();
//分别调用上面封装的方法
pstmtt.loadFile("./libs/db_info.properties");
pstmtt.StatementInsert();
pstmtt.PreparedStatementInsert();
}
}
分别用PreparedStatement和Statement插入100条数据,结果如下:
可以很明显的看出,一个用时:130 ms,一个用时:8 ms用时,PreparedStatement效率要高很多!
为什么它们会运行效率会差这么多?
这是因为PreparedStatement可以预编译,划重点:预编译!
代码中的SQL语句在执行的时候,需要编译的,而 Statement 需要传入100次SQL语句,但是 PreparedStatement 只需要传一条预编译的SQL语句,后面进行100次的传参就好了,每次传入SQL语句都很费时,只需传一次自然要快很多
三、编写复杂程度对比
除了效率区别之外,PreparedStatement还可以使用问号(?)占位符 ,也就是SQL语句中可以用问号代替参数,后面再传参数就好了,而Statement则需要“拼接”SQL字符串,里面有单双引号,语句一长,很容易出错,还编写麻烦
Statement 需要这样写:
//value里面进行字符“拼接”,单双引号,容易出错
executeUpdate("insert into student_table value("+"null ,'姓名" + i + "',1)");
而PreparedStatement:
//不同的记录,用占位符表示,后面再传入参数
preparedStatement("insert into student_table value(1,?,i);
//下面在这样插入参数
setString(1,"姓名",i) //表示第一个占位符的值
四、安全性对比
使用PreparedStatement 还可以防止 SQL注入,SQL注入是利用SQL语句的漏洞来入侵的,如下例子:
有个登录窗口,会根据用户输入的用户名和密码,和数据库里面的 user 表用户数据,进行数据匹配,找到对应的数据,成功,用户登录成功。
SQL语句和判断 部分代码:
//查询语句,其中userName为用户名,userPass为用户密码
String sql = "select * from user " + "where user_name='" + userName + "' and user_pass='" + userPass + "'" ;
......
//如果查询的结果集里面有超过一条的记录,返回true,登录成功
if(stmt.executeQuery(sql)){
return true;
}
......
上面逻辑看似没啥问题,但是,当用户这样输入呢:
用户这样输入后,程序拼接的sql语句是:
select * from user where user_name='' or true or ''and user_pass='';
从这里可以发现,相当于用户可以直接输入 true ,SQL语句也会直接用这个 true ,不用密码就能登录了,但是如果使用的是PreparedStatement,SQL语句会经过验证,自然也就防止了SQL注入
五、PreparedStatement优点总结
使用PreparedStatement不但拥有父接口 Statement 的所有方法,还有以下优点:
- 能预编译SQL语句,执行效率更高,性能更好
- 不用“拼接”SQL语句,减少了编程的复杂,还减少了错误的发生性
- 可以防止SQL注入,安全性更好
综上所述:应该尽量避免使用 Statement,改用PreparedStatement 来执行SQL语句。
标签:语句,PreparedStatement,sql,user,Statement,SQL,放弃 来源: https://www.cnblogs.com/changge333/p/15378289.html