JDBC——预编译(PreparedStatemen与Statement)性能比较 及防止sql注入式攻击

JDBC——预编译(PreparedStatemen与Statement)性能比较 及防止sql注入式攻击,第1张

JDBC——预编译(PreparedStatemen与Statement)性能比较 及防止sql注入式攻击

写在之前:
PreparedStatement和 Statement一样,PreparedStatement也是用来执行sql语句

与创建Statement不同的是,需要根据sql语句创建PreparedStatement
除此之外,还能够通过设置参数,指定相应的值,而不是Statement那样使用字符串拼接——这样使得使用起来不是很方便 需要进行分别归类 比如查询 和 插入等等这些 *** 作 因为它是根据sql语句内容来的不是直接拼接进去

以下示例代码具体感受以下:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
import java.util.Scanner;
import java.sql.PreparedStatement;

public class JDBCtest {
	public static void main(String[] args) {
		Scanner scan =new Scanner(System.in);
		String st="";
		String st1="";
		
		System.out.println("请输入sql语句:(利用statement)");
	    st=scan.nextLine();
	    long start1=System.currentTimeMillis();
	    JDBCtest.nopreexecute(st);
	    long end1=System.currentTimeMillis();
	    System.out.println("using the statement. "+(end1-start1)+" is the  time consumed");
	    
	    System.out.println("请输入sql语句:(利用preparedstatement)");
	    st1=scan.nextLine();
	    long start2=System.currentTimeMillis();
	    JDBCtest.preexecute(st1);
	    long end2=System.currentTimeMillis();
	    System.out.println("using the preparedstatement. "+(end2-start2)+" is the time consumed");
	    
	}
	public static void nopreexecute(String str)
	{
		try {
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException s)
		{
			s.printStackTrace();
		}

		try(
				Connection c=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root","admin");
				Statement s=c.createStatement();
				
				)
		{
			ResultSet rs=s.executeQuery(str);
				
				while(rs.next()) {
					int id=rs.getInt(1);
					String name=rs.getString(2);
					float hp=rs.getFloat(3);
					int damage=rs.getInt(4);
					System.out.printf("%dt%st%ft%dtn",id,name,hp,damage);
				}
		}catch(SQLException e)
		{
			e.printStackTrace();
		}
	}
	
	public static void preexecute(String str)
	{
		try {
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException s)
		{
			s.printStackTrace();
		}

		try(
				Connection c=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root","admin");
				PreparedStatement s=c.prepareStatement(str);
				
				)
		{
			s.setString(1, "heros4");//先设置参数
			ResultSet rs=s.executeQuery();//再执行
				
				while(rs.next()) {//再根据相应字段返回结果集
				
				int id=rs.getInt(1);
				String name=rs.getString(2);
				float hp=rs.getFloat(3);
				int damage=rs.getInt(4);
				System.out.printf("%dt%st%ft%dtn",id,name,hp,damage);
				}
				
		
		}catch(SQLException e)
		{
			e.printStackTrace();
		}
	}
}

分两个方法 来比较用statement和preparedstatement的区别
以下是执行结果:

利用preparedstatement 特别之处就在于要对你在整个字符串的设定的——‘?’ 进行参数设置——s.setString()或者s.setInt()等等此类 *** 作
这种要依据用户输入的sql语句去判断?个数进而去设定参数的序号(序号指的是sql语句中 ?的出现顺序)就挺麻烦的——但是也可以在用户输入的时候就输入表明有几个 ? 要在第几个插入那种数据类型 通过方法传参 依靠这种思路也是可以写出相应方法的
eg:“insert into hero values(null,?,?,?)”;

preparedstatement相较于statement的优点:
1、
Statement 需要进行字符串拼接,可读性和维护性比较差
PreparedStatement 使用参数设置,可读性好,不易犯错

2、
PreparedStatement有预编译机制,性能比Statement更快
从运行结果的图示——statement 195ms 和 preparedstatement 12 ms
就能看出谁快谁慢

以上的图片是查询性能比较

以下是插入性能比较:

3、PreparedStatement 可有效防止sql注入式攻击

什么是sql注入式攻击——就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。
比如以下的sql语句
insert into hero values(null," + str1 + “,”
+ str2 “)”;
str1和str2就是用户输入的 可用注释或者某些符号配合就可以篡改执行命令
因为 str1和str2本是字符串形式 那么就可以以字符串形式写入sql语句

依靠拼接字符串确实省事 但是用户输入恶意sql语句进行拼接 其执行结果就不一样
比如OR 1=1 这无论如何都是true 必定会执行
若知道表名 拼接sql语句——drop table 表名 – (’–'为sql语句中起注释作用) 就可以成功删除对方数据库的表

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5654187.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存