听说都放弃 Statement 而使用 PreparedStatement 去了?

尽量避免使用 Statement,改用PreparedStatement 来执行SQL语句

一、PreparedStatement和Statement的区别和联系

  1. 联系PreparedStatementStatement的子接口,为了满足Statement一些没有的的功能,特意提供的,拥有Statement的所有方法,比如:execute()、executeUpdate()、executeQuery()方法
  2. 区别:PreparedStatement执行SQL语句时,会将语句预编译,存储在PreparedStatement对象中,在执行相同的语句时,可以直接执行,不用多次编译,效率更高,而且,还可以使用"?"这个占位符,当大量数据有相同的列时,就不用每次都编译输入SQL语句,用法如下:
insert into student value(null,?,?);

二、执行效率对比

分别使用StatementPreparedStatement向数据库插入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 需要这样写:

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='';

从这里可以发现,相当于用户可以直接输入 trueSQL语句也会直接用这个 true ,不用密码就能登录了,但是如果使用的是PreparedStatement,SQL语句会经过验证,自然也就防止了SQL注入

五、PreparedStatement优点总结

使用PreparedStatement不但拥有父接口 Statement 的所有方法,还有以下优点:

  1. 能预编译SQL语句,执行效率更高,性能更好
  2. 不用“拼接”SQL语句,减少了编程的复杂,还减少了错误的发生性
  3. 可以防止SQL注入,安全性更好

综上所述:应该尽量避免使用 Statement,改用PreparedStatement 来执行SQL语句。

发布了6 篇原创文章 · 获赞 7 · 访问量 367

猜你喜欢

转载自blog.csdn.net/tanghaixu/article/details/105605734