Statement的缺陷 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 package com.zss.jdbc;import java.sql.*;import java.util.HashMap;import java.util.Map;import java.util.Scanner;public class test { public static void main (String [] args) { Map<String,String> haha= test.initUi(); System.out.println(test.login(haha)?"登陆成功" :"登陆失败" ); } private static Map<String ,String > initUi(){ Scanner scanner=new Scanner (System.in); System.out.println("请输入您的用户名" ); String userName=scanner.nextLine(); System.out.println("请输入您的登录密码" ); String password=scanner.nextLine(); Map<String,String> userInformation=new HashMap <>(); userInformation.put("username" ,userName); userInformation.put("password" ,password); return userInformation; } private static boolean login (Map<String,String> userInformation) { boolean loginY=false ; Connection connection=null ; Statement statement=null ; ResultSet resultset=null ; try { Class.forName("com.mysql.cj.jdbc.Driver" ); connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/userinformation" ,"root" ,"200101" ); statement=connection.createStatement(); String sql="select * from user where 用户名= '" +userInformation.get("username" )+"'and 密码= '" +userInformation.get("password" )+"'" ; resultset=statement.executeQuery(sql); if (resultset.next()){loginY=true ;} } catch (Exception e){e.printStackTrace();} finally { if (resultset!=null ){try {resultset.close();}catch (Exception e){e.printStackTrace();}} if (statement!=null ){try {statement.close();}catch (Exception e){e.printStackTrace();}} if (connection!=null ){try {connection.close();}catch (Exception e){e.printStackTrace();}} } return loginY; } }
大家按照如图中信息去输入,可以惊奇的发现,账号密码完全不对,可是怎么就可以登录???
是因为在编译过程中,数据将密码传输给mysql语句,导致mysql语句句意发生改变,大家仔细查看在调试过程中,sql语句句意发生了改变,导致这个验证根本无效,可以直接通过这个登录。
PreparedStatement 预编译是将语句首先传入,但是将位置用?留出,等到后面在进行传入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 package com.zss.jdbc;import java.sql.*;import java.util.HashMap;import java.util.Map;import java.util.Scanner;public class test { public static void main (String [] args) { Map<String,String> haha= test.initUi(); System.out.println(test.login(haha)?"登陆成功" :"登陆失败" ); } private static Map<String ,String > initUi(){ Scanner scanner=new Scanner (System.in); System.out.println("请输入您的用户名" ); String userName=scanner.nextLine(); System.out.println("请输入您的登录密码" ); String password=scanner.nextLine(); Map<String,String> userInformation=new HashMap <>(); userInformation.put("username" ,userName); userInformation.put("password" ,password); return userInformation; } private static boolean login (Map<String,String> userInformation) { boolean loginY=false ; Connection connection=null ; PreparedStatement preparedStatement=null ; ResultSet resultset=null ; try { Class.forName("com.mysql.cj.jdbc.Driver" ); connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/userinformation" ,"root" ,"200101" ); String sql="select * from user where 用户名= ? and 密码= ? " ; preparedStatement=connection.prepareStatement(sql); preparedStatement.setString(1 ,userInformation.get("username" )); preparedStatement.setString(2 ,userInformation.get("password" )); resultset= preparedStatement.executeQuery(); if (resultset.next()){loginY=true ;} } catch (Exception e){e.printStackTrace();} finally { if (resultset!=null ){try {resultset.close();}catch (Exception e){e.printStackTrace();}} if (preparedStatement!=null ){try {preparedStatement.close();}catch (Exception e){e.printStackTrace();}} if (connection!=null ){try {connection.close();}catch (Exception e){e.printStackTrace();}} } return loginY; } }
说明
在大部分情况下,PreparedStatement 比Statement 更加广泛,而且更加安全。
PreparedStatement 比Statement 运行更加快速,在mysql中,如果连续两条语句一模一样,这样编译器不会对语句进行重新编译,而是直接将? 赋值进行操作。
在部分特殊情况下,还是需要使用Statement, 因为部分企业需求需要进行注入。(比如我们常见的商品按照价格排序界面,需要有order by desc/asc时,利用 PreparedStatement 传输desc值或者asc值时,会为这两个值带上引号,语句无法识别,此时使用Statement 更加方便。