zoukankan      html  css  js  c++  java
  • 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) {
    
        }
    }
    
    
  • 相关阅读:
    Java中参数传递时值传递的机制分析
    掰碎了讲中文编码
    掰碎了讲换行符和回车符
    创建父子控制器
    分页(进行封装处理)
    五:面向对象的三大特性:封装、继承、多态
    iOS9弹框的最新两种方式(解决控制器以外的类无法弹出的问题)
    各类报错汇集
    NBA季后赛结果预测
    十:类的本质及isa指针和元类的简单介绍
  • 原文地址:https://www.cnblogs.com/z5452830/p/14053447.html
Copyright © 2011-2022 走看看