PreparedStatement 对象详解★★★

PreparedStatement★★★

1、练习程序

练习1:用preparedstatement完成Insert编写

练习代码

import com.xy.MySQL.myMethods.JDBCUtils;
import java.sql.*;
import java.util.Date;

public class preparedStatementInsert {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try{
            conn = JDBCUtils.getConnection();
            //接下来和statement有区别
            //先写sql用于接下来的预编译(不执行),使用?占位符代替参数
            String sql = "INSERT INTO users(id,name,password,email,birthday) VALUES(?,?,?,?,?)";//使用?占位符代替参数

            pst = conn.prepareStatement(sql);//预编译SQL,需要先写SQL,但是不执行

            //手动给上边的参数赋值
            //语法为pst.set参数类型(参1,参2)
            //其中参1是下标,从1开始,比如说下边的index为1代表给id赋值
            pst.setInt(1,4);//id为4
            pst.setString(2,"赵六");//name为赵六
            pst.setString(3,"1234567");//name为赵六
            pst.setString(4,"123456@qq.com");//name为赵六
            /*注意点:
            sql.Date  数据库用时  java.sql.Date()
            util.Date Java用时   new Date().getTime() 获取时间戳
            */
            pst.setDate(5,new java.sql.Date(new Date().getTime()));//import java.util.Date
            /*
            插入日期其实也可以用setString的方法,只不过这样插入的就是一行字符串了
            原表的birthday部分的类型必须得是字符串类型
            pst.setString(5,"1990-05-01");
            */

            //直接执行SQL
            int i = pst.executeUpdate();
            if (i>0){
                System.out.println("插入成功!");
            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(conn,pst,null);
        }
    }
}

运行结果


练习2:用preparedstatement完成Delete编写

练习代码

import com.xy.MySQL.myMethods.JDBCUtils;
import java.sql.*;

public class preparedStatementDelete {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try{
            conn = JDBCUtils.getConnection();
            //接下来和statement有区别
            //先写sql用于接下来的预编译(不执行),使用?占位符代替参数
            String sql = "DELETE FROM users WHERE id=?";//使用?占位符代替参数

            pst = conn.prepareStatement(sql);//预编译SQL,需要先写SQL,但是不执行

            //手动给上边的参数赋值
            //语法为pst.set参数类型(参1,参2)
            //其中参1是下标,从1开始,比如说下边的parameterIndex为1代表给id赋值
            pst.setInt(1,4);//id为4
            //直接执行SQL
            int i = pst.executeUpdate();
            if (i>0){
                System.out.println("删除成功!");
            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(conn,pst,null);
        }
    }
}

运行结果


练习3:用preparedstatement完成Update编写

练习代码

import com.xy.MySQL.myMethods.JDBCUtils;
import java.sql.*;

public class preparedStatementUpdate {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try{
            conn = JDBCUtils.getConnection();
            //接下来和statement有区别
            //先写sql用于接下来的预编译(不执行),使用?占位符代替参数
            String sql = "UPDATE users SET name=? WHERE id=?";//使用?占位符代替参数

            pst = conn.prepareStatement(sql);//预编译SQL,需要先写SQL,但是不执行

            //手动给上边的参数赋值
            //语法为pst.set参数类型(参1,参2)
            //其中参1是下标,从1开始,比如说下边的parameterIndex为1代表给name赋值
            pst.setString(1,"张三b");//name为张三b
            pst.setInt(2,1);//id为1
            //直接执行SQL
            int i = pst.executeUpdate();
            if (i>0){
                System.out.println("修改成功!");
            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(conn,pst,null);
        }
    }
}

运行结果


练习4:用preparedstatement完成Select编写

练习代码

import com.xy.MySQL.myMethods.JDBCUtils;
import java.sql.*;

public class preparedStatementSelect {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try{
            conn = JDBCUtils.getConnection();
            //接下来和statement有区别
            //先写sql用于接下来的预编译(不执行),使用?占位符代替参数
            String sql = "SELECT * FROM users WHERE id=?";//使用?占位符代替参数

            pst = conn.prepareStatement(sql);//预编译SQL,需要先写SQL,但是不执行

            //手动给上边的参数赋值
            //语法为pst.set参数类型(参1,参2)
            //其中参1为占位符编号,从1开始,比如说下边的parameterIndex为1代表给id赋值
            pst.setInt(1,2);//id为2
            //直接执行SQL
            rs = pst.executeQuery();
            while (rs.next()) {
                System.out.println("id="+rs.getInt("id"));
                System.out.println("name="+rs.getString("name"));
                System.out.println("password="+rs.getString("password"));
                System.out.println("email="+rs.getString("email"));
                System.out.println("birthday="+rs.getDate("birthday"));
            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(conn,pst,rs);
        }
    }
}

运行结果

id为2处的表格内容


练习5:防止SQL注入测试

练习代码

import com.xy.MySQL.myMethods.JDBCUtils;
import java.sql.*;

public class 防止SQL注入测试 {
    public static void main(String[] args) {

        //正常登录
        //login("张三","123456");

        //sql注入
        //login("'' or 1=1","'' or 1=1");//使用错误的登录信息无法获得用户信息
        login("王五","123456");//使用正确的登录信息成功获得该用户信息
    }

    /**
     * 登录业务
     */
    public static void login(String userName, String password) {
        Connection con = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            con = JDBCUtils.getConnection();
            /*
            PreparedStatement 防止SQL注入的本质:把传递进来的参数作为字符
            假如其中存在转义字符,直接忽略掉,比如说 '会被直接转义
            */
            String sql = "SELECT * FROM users WHERE `name`=? AND `password`=?";
            pst = con.prepareStatement(sql);
            pst.setString(1,userName);
            pst.setString(2,password);

            rs = pst.executeQuery();
            while (rs.next()) {
                System.out.println("id="+rs.getInt("id"));
                System.out.println("name="+rs.getString("name"));
                System.out.println("password="+rs.getString("password"));
                System.out.println("email="+rs.getString("email"));
                System.out.println("birthday="+rs.getDate("birthday"));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.release(con,pst,rs);
        }
    }
}

运行结果

  • 使用错误的登录信息 login("'' or 1=1","'' or 1=1");

    如图所示,没有获得任何用户信息

  • 使用正确的登录信息(表中存在的信息) login("王五","123456");

    如图所示,成功获取该用户的信息


2、总结

1.首先来看一下preparedstatement对象和Statement对象用法在步骤上的区别

  • statement对象

    • 首先声明变量 con,st,rs

      Connection con = null;
      Statement st = null;
      ResultSet rs = null;
      
    • 获取连接,创建statement对象,定义带参数的sql语句,执行sql语句(try)

      con = JDBCUtils.getConnection();//获取连接
      st = con.createStatement();//创建statement对象
      String sql = "UPDATE users SET birthday='1990-12-01' WHERE id=1";//定义带参sql
      int num = st.executeUpdate(sql);//执行sql语句
      
    • 捕获异常(catch)

      catch (SQLException e) {
      	e.printStackTrace();
      }
      
    • 最后释放连接(finally)

      finally{
          JDBCUtils.release(con, st, rs);
      }
      
  • preparedstatement对象

    • 首先声明变量 con,st,rs

      Connection con = null;
      Statement st = null;
      ResultSet rs = null;
      
    • 获取连接

      con = JDBCUtils.getConnection();
      
    • 之后就开始和statement对象有区别了

      • 首先要写不带参的sql用于接下来的预编译(不执行),使用 ? 占位符代替参数,比如说:

        String sql = "SELECT * FROM users WHERE id=?";
        
      • 然后创建preparedstatement对象对SQL进行预编译(不执行)

        pst = conn.prepareStatement(sql);
        
      • 再然后手动给上边的不带参参数赋值,语法为pst.set参数类型(参1,参2)
        其中参1为占位符 ? 的位置从1开始

        比如说下边的例子中,参1和参2分别为 1 和 2 代表给 ? 位置为 1 的 id 赋值为 2

        pst.setInt(1,2)
        
      • 最后执行sql语句,需要注意的是这里的执行不用带参

        rs = pst.executeQuery();//不带参执行
        rs = pst.executeQuery(sql);//带参执行
        
    • 捕获异常和释放连接不再赘述


2.preparedstatement对象可以防止SQL注入

PreparedStatement 防止SQL注入的本质:把传递进来的参数作为字符

假如其中存在转义字符,直接忽略掉,比如说 ' 会被直接转义


3、setDate问题(存疑)

import com.xy.MySQL.myMethods.JDBCUtils;
import java.sql.*;
import java.util.Date;

public class preparedStatementInsert {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try{
            conn = JDBCUtils.getConnection();
            //接下来和statement有区别
            //先写sql用于接下来的预编译(不执行),使用?占位符代替参数
            String sql = "INSERT INTO users(id,name,password,email,birthday) VALUES(?,?,?,?,?)";//使用?占位符代替参数

            pst = conn.prepareStatement(sql);//预编译SQL,需要先写SQL,但是不执行

            //手动给上边的参数赋值
            //语法为pst.set参数类型(参1,参2)
            //其中参1是下标,从1开始,比如说下边的index为1代表给id赋值
            pst.setInt(1,4);//id为4
            pst.setString(2,"赵六");//name为赵六
            pst.setString(3,"1234567");//name为赵六
            pst.setString(4,"123456@qq.com");//name为赵六
            /*注意点:
            sql.Date  数据库用时  java.sql.Date()
            util.Date Java用时   new Date().getTime() 获取时间戳
            */
            pst.setDate(5,new java.sql.Date(new Date().getTime()));//import java.util.Date
            /*
            插入日期其实也可以用setString的方法,只不过这样插入的就是一行字符串了
            原表的birthday部分的类型必须得是字符串类型
            pst.setString(5,"1990-05-01");
            */

            //直接执行SQL
            int i = pst.executeUpdate();
            if (i>0){
                System.out.println("插入成功!");
            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            JDBCUtils.release(conn,pst,null);
        }
    }
}

sql.Date和java.Date完全不同,这个问题比较头疼,比如说

在上边这个练习中,我想插入一个自定义日期而不是当前日期,应该怎么办呢

没啥头绪,回看~~

posted @   无关风月7707  阅读(248)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示