jdbc(2)

1.sql注入安全问题

 public static void main(String[] args) throws Exception {
        Scanner sc=new Scanner(System.in);
        System.out.print("请输入账号:");
        String name=sc.nextLine();
        System.out.print("请输入密码:");
        String pwd=sc.nextLine();
        boolean flag = login(name, pwd);
        if(flag==true){
            System.out.println("登录成功,跳转主页面");
        }else{
            System.out.println("账号或密码错误.");
        }
    }
    //登录方法。
    private static boolean login(String name,String pwd) throws Exception{
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url="jdbc:mysql://localhost:3306/qy174";
        String user="root";
        String password="root";
        Connection conn= DriverManager.getConnection(url,user,password);
        Statement st=conn.createStatement();

        String sql="select * from tbl_user where username='"+name+"' and password='"+pwd+"'";
        System.out.println(sql);
        ResultSet rs=st.executeQuery(sql);
        while (rs.next()){
            return true; //方法遇到return 方法结束。
        }
        return false;
    }


处理sql注入安全隐患问题。Statement这个类导致出现了bug. 创建了一个新的接口,该接口继承Stetement接口,并加入了自己新的功能。子接口就是PrepareStatement. s该类可以解决sql注入安全问题。

 public static void main(String[] args) throws Exception {
        Scanner sc=new Scanner(System.in);
        System.out.print("请输入账号:");
        String name=sc.nextLine();
        System.out.print("请输入密码:");
        String pwd=sc.nextLine();
        boolean flag = login2(name, pwd);
        if(flag==true){
            System.out.println("登录成功,跳转主页面");
        }else{
            System.out.println("账号或密码错误.");
        }
    }
    //我们以后执行sql时,都使用PreparedStatement.
    private static boolean login2(String name,String pwd) throws Exception{
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url="jdbc:mysql://localhost:3306/qy174";
        String user="root";
        String password="root";
        Connection conn= DriverManager.getConnection(url,user,password);
        //占位符:
        String sql="select * from tbl_user where username=? and password=?";
        PreparedStatement ps=conn.prepareStatement(sql); //预编译
        //为占位符赋值
        ps.setString(1,name); //1.表示第几个占位符.   name表示占位符的值
        ps.setString(2,pwd);
        //不用在写sql.
        ResultSet rs=ps.executeQuery();
        while (rs.next()){
            return true; //方法遇到return 方法结束。
        }
        return false;
    }

原因:因为sql的字符串拼接导致sql注入安全问题。 为使用占位符并为占位符赋值的方式可以解决sql注入问题。
2.异常处理

private static boolean login2(String name, String pwd) {
        ResultSet rs = null;
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/qy174";
            String user = "root";
            String password = "root";
            conn = DriverManager.getConnection(url, user, password);
            //占位符:
            String sql = "select * from tbl_user where username=? and password=?";
            ps = conn.prepareStatement(sql); //预编译
            //为占位符赋值
            ps.setString(1, name); //1.表示第几个占位符.   name表示占位符的值
            ps.setString(2, pwd);
            //不用在写sql.
            rs = ps.executeQuery();
            while (rs.next()) {
                return true; //方法遇到return 方法结束。
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            //资源关闭代码 --关闭时的顺序. 后用先关。
            try {
                if (rs != null) {
                    rs.close();//关闭资源
                }
                if(ps!=null){
                    ps.close();
                }
                if(conn!=null){
                    conn.close();
                }
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        return false;
    }

3. 企业开发模式
把对表的操作封装到dao类中
dao层: data access object(数据访问对象层) 以后我们对表的操作习惯放在dao包下。每张表对应一个dao类。而该类中包含所有数据该表的操作【crud】。
比如: tbl_user表---->UserDao类该类中包含了对该tbl_user表操作的各种方法。 tbl_teacher---->TeacherDao类。

package com.ykq.dao;

import java.sql.*;

public class UserDao { //类的命名: 首字母必须大写。而且按照驼峰命名[每个单词的首字符必须大写]。

    //方法名命名: 第一个单词的首字母小写。
    public void selectById(int id){
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            //1. 加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2. 获取连接对象
            String url = "jdbc:mysql://localhost:3306/qy174";
            String user = "root";
            String password = "root";
            conn = DriverManager.getConnection(url, user, password);
            //3. 获取执行sql语句的对象。PreparedStatement
            String sql = "select * from tbl_user where id=?";
            ps = conn.prepareStatement(sql);
            //4. 为占位符赋值
            ps.setInt(1, id);
            //5.执行sql.
            ResultSet rs = ps.executeQuery();
            //6.遍历
            while (rs.next()){
                int id1 = rs.getInt("id");
                String username = rs.getString("username");
                String password1 = rs.getString("password");
                String realname = rs.getString("realname");
                System.out.println("编号:"+id+";账号:"+username+";密码:"+password1+";真实姓名:"+realname);
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }


    /**
     * 修改
     * @param id
     * @param name
     * @param pwd
     * @param realname
     * @return
     */
    public int updateById(int id,String name,String pwd,String realname){
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            //1. 加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2. 获取连接对象
            String url = "jdbc:mysql://localhost:3306/qy174";
            String user = "root";
            String password = "root";
            conn = DriverManager.getConnection(url, user, password);
            //3. 获取执行sql语句的对象。PreparedStatement
            String sql = "update tbl_user set username=?,password=?,realname=? where id=?";
            ps = conn.prepareStatement(sql);
            //4. 为占位符赋值
            ps.setString(1,name);
            ps.setString(2,pwd);
            ps.setString(3,realname);
            ps.setInt(4, id);
            //5.执行sql.
            int i = ps.executeUpdate();
            return i;
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 根据id删除
     * @param id 主键值
     * @return 影响的行数
     */
    public int deleteById(int id){
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            //1. 加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2. 获取连接对象
            String url = "jdbc:mysql://localhost:3306/qy174";
            String user = "root";
            String password = "root";
            conn = DriverManager.getConnection(url, user, password);
            //3. 获取执行sql语句的对象。PreparedStatement
            String sql = "delete from tbl_user where id=?";
            ps = conn.prepareStatement(sql);
            //4. 为占位符赋值
            ps.setInt(1, id);
            //5.执行sql.
            int i = ps.executeUpdate();
            return i;
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
               e.printStackTrace();
            }
        }
    }


    /**
     * 添加用户的功能
     *
     * @param name     账号
     * @param pwd      密码
     * @param realname 真实姓名
     * @return 影响的条数
     */
    public int insertUser(String name, String pwd, String realname) {
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            //1. 加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2. 获取连接对象
            String url = "jdbc:mysql://localhost:3306/qy174";
            String user = "root";
            String password = "root";
            conn = DriverManager.getConnection(url, user, password);
            //3. 获取执行sql语句的对象。PreparedStatement
            String sql = "insert into tbl_user values(null,?,?,?)";
            ps = conn.prepareStatement(sql);
            //4. 为占位符赋值
            ps.setString(1, name);
            ps.setString(2, pwd);
            ps.setString(3, realname);
            //5.执行sql.
            int i = ps.executeUpdate();
            return i;
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }


    }
}

把表中的数据封装到entity类中。
我们以后把查询的记录结果封装到我们的实体类中。为了在网页中展示。 我们上面写的查询操作,都是在控制台打印的。
我们就应该把查询的结果封装到java类对象中,调用者就可以获取该java类对象。展示对应的数据了。 我们习惯把数据
库中表记录封装到对应的实体类中。 比如: tbl_user---->User实体类。

 //查询用户表中所有的记录.
    public List<User> selectAll() throws Exception{
        Connection conn=null;
        PreparedStatement ps=null;
        //创建集合容器
        List<User> list = new ArrayList<>();
        //1. 加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2. 获取连接对象
        String url = "jdbc:mysql://localhost:3306/qy174";
        String user = "root";
        String password = "root";
        conn = DriverManager.getConnection(url, user, password);
        //3.获取执行sql语句的对象。PreparedStatement
        String sql = "select * from tbl_user";
        ps = conn.prepareStatement(sql);
        //4.执行sql
        ResultSet rs=ps.executeQuery();
        while (rs.next()){
             User user1=new User();//创建实体类对象
             user1.setId(rs.getInt("id"));
             user1.setUsername(rs.getString("username"));
             user1.setPassword(rs.getString("password"));
             user1.setRealname(rs.getString("realname"));
             list.add(user1);//把java实体类对象放入集合中
        }
        return list;
    }

    //方法名命名: 第一个单词的首字母小写。
    public User selectById(int id) throws Exception {
        PreparedStatement ps = null;
        Connection conn = null;
        User u = null;//声明一个User类的实体类
        //1. 加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2. 获取连接对象
        String url = "jdbc:mysql://localhost:3306/qy174";
        String user = "root";
        String password = "root";
        conn = DriverManager.getConnection(url, user, password);
        //3. 获取执行sql语句的对象。PreparedStatement
        String sql = "select * from tbl_user where id=?";
        ps = conn.prepareStatement(sql);
        //4. 为占位符赋值
        ps.setInt(1, id);
        //5.执行sql.
        ResultSet rs = ps.executeQuery();
        //6.遍历
        while (rs.next()) {
            u = new User(); //实例化类对象
            //查询当前记录中对应列的值
            int id1 = rs.getInt("id");
            String username = rs.getString("username");
            String password1 = rs.getString("password");
            String realname = rs.getString("realname");
            //为实体类的属性赋值
            u.setId(id1);
            u.setUsername(username);
            u.setPassword(password1);
            u.setRealname(realname);
        }
        return u;


    }

总结: 1. 查询的表--封装了实体类---- 字段名---实体类的属性名 表中一条记录---对应实体类的一个对象中。

posted on 2024-12-07 14:31  小木不痞  阅读(9)  评论(0)    收藏  举报

导航