JDBC预处理对象prepareStatement概述

一、SQL注入问题

SQL注入:用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL真正的意义。
假设有登录案例SQL语句如下:
SELECT * FROM 用户表 WHERE NAME = 用户输入的用户名 AND PASSWORD = 用户输的密码;
此时,当用户输入正确的账号与密码后,查询到了信息则让用户登录。但是当用户输入的账号为XXX 密码为:XXX’ OR ‘a’=’a时,则真正执行的代码变为:
SELECT * FROM 用户表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’ OR ’a’=’a’;
此时,上述查询语句时永远可以查询出结果的。那么用户就直接登录成功了,显然我们不希望看到这样的结果,这便是SQL注入问题。
为此,我们使用PreparedStatement来解决对应的问题。

二、代码演示SQL注入问题

(1)数据库准备

代码如下:

#创建sql_into数据库
CREATE DATABASE sql_into;
#使用sql_into数据库
USE sql_into;
#创建sql_into用户表
CREATE TABLE users(uid INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(200),PASSWORD VARCHAR(200)
);
#加入用户信息
INSERT INTO users(username,PASSWORD) VALUES('xiaoming','123'),('xiaoliang','456');
#查询用户信息
SELECT *FROM users;

mysql代码演示

(2)创建用户登录界面

public class StatementMyCode {public static void main(String[] args) throws SQLException {Scanner sc=new Scanner(System.in);System.out.println("请输入用户名:");String username =sc.nextLine();System.out.println("请输入密码:");String password=sc.nextLine();
//获取JDBCUtils连接Connection con=JDBCUtils1.getConnection();//Connection con= JDBCUtils1.getConnection();
//获取Statedment对象Statement stat=con.createStatement();
//执行SQL语句String sql = "select * from users where username='"+username+"' and password ='"+password+"'";System.out.println(sql);ResultSet rs=stat.executeQuery(sql);if(rs.next()){System.out.println("登录成功!");}else{System.out.println("登录失败!");}JDBCUtils1.close(rs,stat,con);}
}

SQL注入出现的登录BUG

(3)配置文件代码

配置文件代码文件名需要和JDBCUtils1里的工具类的配置文件保持一致,配置文件代码文件名为config.properties
className=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/sql_into
user=root
password=root

(4)JDBCUtils1文件代码

public class JDBCUtils1 {private static String url;private static String user;private static String password;private static String className;private JDBCUtils1(){}static {try{Properties p=new Properties();InputStream in = JDBCUtils1.class.getClassLoader().getResourceAsStream("config.properties");p.load(in);in.close();url=p.getProperty("url");user=p.getProperty("user");password=p.getProperty("password");className=p.getProperty("className");//注册驱动Class.forName(className);}catch (Exception e){e.printStackTrace();}
}public static Connection getConnection(){//获取连接Connection con=null;try {con= DriverManager.getConnection(url,user,password);return con;} catch (SQLException e) {throw new RuntimeException("连接失败");}}public static void close(ResultSet rs, Statement stat,Connection con){try {if(rs!=null)rs.close();} catch (SQLException e) {e.printStackTrace();}try {if(stat!=null)stat.close();} catch (SQLException e) {e.printStackTrace();}try {if (con!=null)con.close();} catch (SQLException e) {e.printStackTrace();}}
}

三、防止SQL注入 使用预处理对象

(1)原理介绍

preparedStatement:预编译对象,是Statement对象的子类。
特点:

  • 性能高
  • 会把sql语句先编译
  • 能过滤掉用户输入的关键字。
    PreparedStatement预处理对象,处理的每条sql语句中所有的实际参数,都必须使用占位符?替换。
    String sql = "select * from user where username = ? and password = ?";

PreparedStatement使用,需要通过以下3步骤完成:

  1. PreparedStatement预处理对象代码:
    // 获得预处理对象,需要提供已经使用占位符处理后的SQL语句
    PreparedStatement psmt = conn.prepareStatement(sql)
  2. 设置实际参数
    void setXxx(int index, Xxx xx) 将指定参数设置指定类型的值
    参数1:index 实际参数序列号,从1开始。
    参数2:xxx 实际参数值,xxx表示具体的类型。
    例如:
    setString(2, “1234”) 把SQL语句中第2个位置的占位符?替换成实际参数 “1234”
  3. 执行SQL语句:
    int executeUpdate(); --执行insert update delete语句.
    ResultSet executeQuery(); --执行select语句.
    boolean execute(); --执行select返回true 执行其他的语句返回false.

(2)使用preparedStatement

用户登录界面代码演示

public class prepareStatementMyCode {public static void main(String[] args) throws SQLException {Scanner sc=new Scanner(System.in);System.out.println("请输入用户名:");String username =sc.nextLine();System.out.println("请输入密码:");String password=sc.nextLine();
//获取JDBCUtils连接Connection con=JDBCUtils1.getConnection();//Connection con= JDBCUtils.getConnection();
//获取Statedment对象Statement stat=con.createStatement();
//执行SQL语句String sql = "select * from users where username=? and password =?";PreparedStatement ps = con.prepareStatement(sql);ps.setObject(1,username);ps.setObject(2,password);System.out.println(sql);ResultSet rs=ps.executeQuery();if(rs.next()){System.out.println("登录成功!");}else{System.out.println("登录失败!");}JDBCUtils1.close(rs,stat,con);}
}

正确执行代码演示结果

SQL注入代码演示

四、使用prepareStatement完成查询数据

代码如下:

public class prepareStatementCSDNSelect {public static void main(String[] args) {//获取连接对象Connection con=null;PreparedStatement ps= null;ResultSet rs = null;try {con= JDBCUtils1.getConnection();String sql="select * from users";ps = con.prepareStatement(sql);rs = ps.executeQuery();while(rs.next()){int uid=rs.getInt("uid");String username=rs.getString("username");String password=rs.getString("password");System.out.println(uid+"  "+username+"  "+password);}} catch (SQLException e) {throw  new RuntimeException(e);}finally {JDBCUtils1.close(rs,ps,con);}}
}

使用prepareStatement完成查询

五、使用prepareStatement和javabean类完成查询

(1)创建user1类

代码如下:

/*一个类具备私有成员变量 空参构造方法  get/set 方法   实现序列化接口 那么称这个类为javabean类*/
public class User1 {private int uid;private String username;private   String password;public User1() {}public User1(int uid, String username, String password) {this.uid = uid;this.username = username;this.password = password;}public int getUid() {return uid;}public void setUid(int uid) {this.uid = uid;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User1{" +"uid=" + uid +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}

(2)使用把每条记录封装到user1对象中 将多个user1对象放到list集合当中

/*查询所有记录 把每条记录封装到user1对象中 将多个user1对象放到list集合当中*/
public class prepareStatementCSDNSelectBean {public static void main(String[] args) {//获取连接对象Connection con=null;PreparedStatement ps= null;ResultSet rs = null;try {con= JDBCUtils1.getConnection();String sql="select * from users";ps = con.prepareStatement(sql);rs = ps.executeQuery();//定义一个集合用来存储user对象List<User1>  list=new ArrayList<>();while(rs.next()){int uid=rs.getInt("uid");String username=rs.getString("username");String password=rs.getString("password");User1 u=new User1(uid,username,password);list.add(u);// System.out.println(uid+"  "+username+"  "+password);}System.out.println(list);} catch (SQLException e) {throw  new RuntimeException(e);}finally {JDBCUtils1.close(rs,ps,con);}}
}

查询结果演示

JDBC预处理对象prepareStatement相关推荐

  1. 预处理对象executeQuery方法,对数据库进行有条件和无条件的查询

    (1)通过预处理对象的executeQuery方法,完成记录的select语句的执行: (2)操作格式统一如下: ①注册驱动: ②获取连接: ③获取预处理对象: ④SQL语句占位符设置实际参数: ⑤执 ...

  2. com.microsoft.sqlserver.jdbc.SQLServerException: 对象名 'Monkey' 无效。

    主要代码 package chp13;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLExc ...

  3. JDBC数据对象存储

    一:将查询的结果生成对象,储存在数组中. 1 package day31; 2 3 import java.sql.Connection; 4 import java.sql.PreparedStat ...

  4. 梦回JDBC —— (Statement对象)

    Statement对象 jdbc中的statement 对象用于向数据库发送sql语句,想完成对数据库的增删改查,只需要通过 这个对象发送增删改查的语句就好. statement对象的executeU ...

  5. jdbc连接对象的获取 20210409233805735

    目标 利用jdbc获取连接对象 明确要连哪一个库 关注一个类 新建一个java文件 作为测试类 注册驱动 加载驱动 刚刚看到的Driver类 解决报错 获得连接对象 需要的内容 连接字符串 用户名 密 ...

  6. java 输入流关闭顺序_Java IO流中先关闭输出流还是先关闭输入流?为什么?

    java中需要手动释放的资源bai常见的有以下两个: 流相du关资zhi源 流相关资源一般遵循: 1)先开后关dao,先开的输入流,再开的输出流,通过读取输入流写入输出流中,那么应该先关输出流,再关输 ...

  7. spring基础概述

    1.Spring概述Spring是分层的java SE/EE应用 full-stack 轻量级开源框架,以IOC(Inverse of control)翻转控制和AOP(Aspect Oriented ...

  8. java jpeg rpg_史上最骚RPG制作第三期 java端数据的插入和查询

    简述 在第一个场景我们输入好账号密码和昵称之后,点击开始游戏此时的游戏账号就应该插入到角色这个表里,本期的任务就是了解如何在java里插入数据以及查找数据. jdbc的一些驱动类 DriverMana ...

  9. JDBC:数据库操作:处理大对象CLOB数据

    目标: 了解大对象处理基本原理, 掌握CLOB数据的读,写操作. 可以使用CLOB类处理大文本数据. 大对象处理主要指CLOB和BLOB两种类型字段.可以大量存储文字. 要想在程序中处理这样的大数据操 ...

最新文章

  1. tf.keras.losses.categorical_hinge 分类铰链 损失函数 示例
  2. c语言把地址用%d输出字符串,C语言必须要记住的经典程序
  3. linux指定查看文件目录,【Linux】查看指定目录下的每个文件或目录的大小
  4. ES6之Module 的加载实现(2)
  5. Python OOP:面向对象基础,定义类,创建对象/实例,self,创建多个对象,添加对象属性,访问对象属性,__init__方法,带参数的__init__,__str__方法,__del__方法
  6. 初识ProtoBuf(3.18.1)
  7. 破茧成蝶2——以产品为中心的设计革命
  8. 东南大学毕业论文latex模板
  9. 小米路由器安装Linux软件,小米路由器mini安装mixbox教程
  10. 德州仪器官网TI实时监控自动抢购下单
  11. Python -- 关于函数的学习(五) — 传递任意数量的实参
  12. DV EV OV证书
  13. linux桌面lxde 安装_Ubuntu怎么安装轻量级的LXDE桌面?
  14. 编程计算并输出1 - n之间的所有数的平方和立方。其中n值由用户从键盘输入
  15. 基于TCGA及SEER等癌症公共数据库的深度挖掘和科研设计会议
  16. office实操技能01:修改微软Office页面的(非背景的)浅绿底色、设置默认字体和主题颜色、取消页眉横线、PPT默认的等线字体
  17. 详解如何在vue项目中使用lodop打印插件,以及样式打印预览缺失的问题(底部)
  18. .bat文件打开闪退
  19. 2021年10月24日马丁加德纳聚会线上主题分享开启通知
  20. 用C语言计算手机的九宫格图案解锁总共能绘出多少种图案

热门文章

  1. hibernate删除记录_Hibernate记录:常见问题的提示和解决方案
  2. java中的jpa_在JPA中处理Java的LocalDateTime
  3. jdk 9和jdk8_JDK 9已完成功能!
  4. akka和rabbitmq_Akka Notes –演员记录和测试
  5. moreunit_MoreUnit与MoreUnit
  6. 5个令人震惊的统计数据证明日志不足
  7. activemq优先级_ActiveMQ消息优先级:工作原理
  8. mongodb身份验证_MongoDB身份验证
  9. 枚举:如何正确使用name()和toString()方法
  10. 使用JMX作为Ganglia的现代替代品进行CLDB监视