写在之前:
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语句中起注释作用) 就可以成功删除对方数据库的表
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)