Java-JDBC的预编译与封装

一、PreparedStatement 预编译SQL执行器

​ 由于在登陆功能中,出现任意字符都可以登录,导致该功能有“bug” ,其原因是Statement在执行的sql语句中,其参数注入sql关键字的问题,导致sql失效

​ 可以使用Statement的子接口PreparedStatement解决sql注入异常

使用参数占位

 public static boolean userLogin(String username,String password){
        // 使用jdbc
        // 导入jar包
        // 加载驱动类
        Connection conn=null;
        PreparedStatement pst=null;

        ResultSet rs = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            String url="jdbc:mysql://localhost:3306/j2008_db?useSSL=false&serverTimezone=GMT%2B8";
            //获取连接对象
            conn = DriverManager.getConnection(url,"root","123456");
            //执行SQL语句    对于参数使用?占位
            String sql ="select * from my_user where user_name=? and user_password=?";
            // 获取预编译的sql执行器
            pst = conn.prepareStatement(sql);
            //设置参数  : 有多少个?需要设置多少个参数 参数类型和问号的字段类型一致
            pst.setString(1 , username );
            pst.setString(2, password);

            //执行sql语句
            rs= pst.executeQuery();
            if(rs.next()){
                return true;
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally{
            try{
                if(rs!=null){
                    rs.close();
                }
                if(pst!=null){
                    pst.close();
                }
                if(conn!=null){
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

用户注册:

  // 使用Prepared完成用户注册功能
    public static boolean register (String username,String password ,int age, String sex ){
        // 使用jdbc
        // 导入jar包
        // 加载驱动类
        Connection conn=null;
        PreparedStatement pst=null;

        ResultSet rs = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/j2008_db?useSSL=false&serverTimezone=GMT%2B8";
            //获取连接对象
            conn = DriverManager.getConnection(url, "root", "123456");
            String sql="insert into my_user values(null,?,?,?,?,now())";
            // 获取预编译sql执行器
            pst = conn.prepareStatement(sql);
            //设置参数
            pst.setString(1,username);
            pst.setString(2,password);
            pst.setInt(3,age);
            pst.setString(4,sex);
            int count =  pst.executeUpdate();  //不能有sql参数 否则会覆盖之前的sql模板
             if(count>0){
                 return true;
             }

        }catch(Exception ee){
            ee.printStackTrace();
        }finally{
            try{
                if(rs!=null){
                    rs.close();
                }
                if(pst!=null){
                    pst.close();
                }
                if(conn!=null){
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

对于在添加数据时,主键通常是自增长,如果想要在添加数据成功后,反向获取该主键 ,需要在添加sql是设置一个标识 Statement.RETURN_GENERATED_KEYS

并通过 getGenerateKeys() 获取主键id

Statement.RETURN_GENERATED_KEYS

rs = pst.getGeneratedKeys();

    // 获取预编译sql执行器
            pst = conn.prepareStatement(sql ,Statement.RETURN_GENERATED_KEYS);
            //设置参数
            pst.setString(1,"张三");
            pst.setString(2,"123");
            pst.setInt(3,22);
            pst.setString(4,"男");
            // 通过系统时间 设置 Date
            String str="2020-09-09";
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
             java.util.Date dd =   sdf.parse(str);
            pst.setDate(5,new Date(dd.getTime()));
            // 执行
           int count =  pst.executeUpdate();
           if(count>0){
               //获取主键id
              rs =  pst.getGeneratedKeys();
              //将结果集往后移动一位
              rs.next();
               System.out.println("添加成功,其id:"+rs.getInt(1));
           }
// 应用场景:  需要添加订单表(主表)和订单明细表(子表)
// 先添加订单主表 ,此时会生成订单主键 id
// 再添加多条订单明细:  添加明细是 其它所属的 订单id也需要同时添加, 这是 可以通过getGeneraterKeys 和获取
//  orderId

二、封装DBUtil

package com.j2008.jdbc2;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * ClassName: DBUtil
 */
public class DBUtil {
    static String driverClass;
    static String url;
    static String username;
    static String password;

    static {
        try {
            // 加载驱动
            Class.forName(driverClass);
            // 读取db.propertes 文件
            // 1、根据当前类的类加载器获取文件地址的输入流
            InputStream is = DBUtil.class.getClassLoader().
                    getResourceAsStream("db.properties");
            // 读取类路径的相对地址
            Properties pro = new Properties();
            // 通过属性工具类将一个属性文件的输入流加载(序列化的过程)
            pro.load(is);
            // getProperty(key)
            driverClass = pro.getProperty("driverClass");
            url = pro.getProperty("url");
            username = pro.getProperty("username");
            password = pro.getProperty("password");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据连接
     */
    public static Connection getConn() {
        Connection conn = null;
        try {
            // 获取连接
            conn = DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;


    }

    /**
     * 关闭所有连接
     * @param conn
     * @param st
     * @param rs
     */
    public void closeAll(Connection conn , Statement st , ResultSet rs){
         try{
             if(rs!=null){
                 rs.close();
             }
             if(st!=null){
                 st.close();
             }
             if(conn!=null){
                 conn.close();
             }
         }catch (Exception ee ){
            ee.printStackTrace();
         }
    }

    public static void main(String[] args) {

    }
}

posted @ 2020-11-28 18:04  落雨♡̶初晴  阅读(236)  评论(0编辑  收藏  举报