栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

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

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语句中起注释作用) 就可以成功删除对方数据库的表

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/652056.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号