程序员

009-JDBC,防SQL注入

2020-03-16  本文已影响0人  Ktry

DBC

Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。

JDBC的开发步骤

/**
 * 0、准备工作:导入jar包
 *         a、在工程下新建一个lib文件夹
 *     b、将数据库驱动包,放入到文件夹中,并添加到classpath中
 *              右击jar包,build path ---- >  add to build path     
 * 1、注册驱动
 *             a、DriverManager类的resgister方法来注册驱动
 *             b、利用反射技术来注册驱动
 *  Class.forName("com.mysql.jdbc.Driver");
 *     2、获取数据库连接对象
 *  Connection conn  = DriverManager.getConnection(url,username,password); 
 * 
 * 3、获取数据库操作对象
 * Statement stat = conn.createStatement();
 * 
 * 4、执行sql语句,获取结果集    
 * String sql = "xxxxx";
 * int count = stat.executeUpdate(sql);
 * 
 * 5、处理结果集
 * System.out.println(count);
 * 
 * 6、关闭资源
 * stat.close();
 * conn.close();
 * 
 */

JDBC代码实现

public class JDBCDemo1 {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        //1、注册驱动
//        Driver driver = new Driver();
//        DriverManager.registerDriver(driver);
        //全限定名  包名+类名   执行这句话,相当于类被加载了,通过原码发现,这个Driver类被加载,他的静态代码块就会被执行,驱动就注册上了
        Class.forName("com.mysql.jdbc.Driver");

        //2、获取数据库连接对象Connection对象
        /*
         *     url  连接数据库的地址  
         * 网络通信三要素     ip地址  协议    端口
         *  http://www.baidu.com:80
         *  本机的回路地址 :localhost    127.0.0.1   192.168.71.40
         *  
         *  jdbc:mysql://localhost:3306/数据库名
         *  如果是连接的本机的数据库可以简写为:
         *  jdbc:mysql:///数据库名
         * 
         *     在5.7的版本中,运行程序会有警告,SSL协议不可用
         * jdbc:mysql:///数据库名?useSSL=false
         * 
         * 
         *     user   数据库用户名
         *  password  数据库密码
         * 
         * */
        String url = "jdbc:mysql:///java?useSSL=false";
        String user = "root";
        String password = "root";
        Connection conn = DriverManager.getConnection(url, user, password);

        //System.out.println(conn);

        //3、获取Statement对象操作数据库
        Statement stat = conn.createStatement();

        //4、执行sql语句并,返回结果集
        /* 
         *  针对的增删改    
         *     stat.executeUpdate(sql)    返回值是受影响行数
         *  针对的是查询
         *     stat.executeQuery(sql)      结果集
         * */
        String sql = "insert into student values(1,'zhangsan','1班')";
        int count = stat.executeUpdate(sql);
        //5、处理结果
        System.out.println("受影响的行数为"+count);
        //6、关闭资源
        stat.close();
        conn.close();

    }
}

JDBC实现查询

public class JDBCDemo2 {
    public static void main(String[] args) {
        ResultSet rs = null;
        Statement stat = null;
        Connection conn = null;
        try {
            //1、注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2、获取数据库连接对象Connection
            String url = "jdbc:mysql:///java?useSSL=false";
            String user = "root";
            String password = "root";
            conn = DriverManager.getConnection(url, user, password);
            //3、获取数据操作对象
            stat = conn.createStatement();
            //4、通过Statement对象执行SQL语句,返回ResultSet结果集
            String sql = "select * from student";
            rs = stat.executeQuery(sql);
            /**
             * rs.next(); 判断是否有下一个,如果有将游标往下移动一位,返回true。,如果没有返回false
             * 
             * rs.getXXX 方法  用与从结果集中获取数据。
             *  XXX 取决于数据在数据库中的类型
             *  int    ------ > getInt("字段名");
             *  double ----> getDouble("字段名");
             *  varchar ---->getString("字段名");
             *  date ------>getDate("字段名");
             *  
             */
//            rs.next();
//            int sid = rs.getInt("sid");
//            String sname = rs.getString("sname");
//            String scalss = rs.getString("sclass");
//            System.out.println(sid);
//            System.out.println(sname);
//            System.out.println(scalss);
            //5、处理结果集
            while(rs.next()) {
                int sid = rs.getInt("sid");
                String sname = rs.getString("sname");
                String sclass = rs.getString("sclass");
                System.out.println(sid);
                System.out.println(sname);
                System.out.println(sclass);
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //6、关闭资源
            /**
             *  rs 对象、  stat 对象、conn 对象
             */
            try {
                if(rs != null) {
                    rs.close();
                }
                if(stat != null) {
                    stat.close();
                }
                if(conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }        
    }
}

ORM思想

对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。

ORM代码实现

public class JDBCDemo3 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        //1、注册驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
            //2、获取数据库连接对象 Connection
            conn = DriverManager.getConnection("jdbc:mysql:///java", "root", "root");
            //3、获取Statement对象 
            stat = conn.createStatement();
            //4、执行sql语句获取结果集
            rs = stat.executeQuery("select * from student");

            //定义一个List集合用于存放结果集中的数据
            List<Student> list = new ArrayList<Student>();
            //5、处理结果集
            while(rs.next()) {
                Student stu = new Student();

                //从结果集中一行获取数据
                int sid = rs.getInt("sid");
                String sname = rs.getString("sname");
                String sclass = rs.getString("sclass");

                //将结果添加到对象中
                stu.setSid(sid);
                stu.setSname(sname);
                stu.setSclass(sclass);

                //将对象添加到List集合中
                list.add(stu);
            }
            System.out.println(list);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //关闭资源
            try {
                if(conn != null) {
                    conn.close();
                }
                if(stat != null) {
                    stat.close();
                }
                if(rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

ORM的核心代码

//定义一个List集合用于存放结果集中的数据
List<Student> list = new ArrayList<Student>();
//5、处理结果集
while(rs.next()) {
    Student stu = new Student();

    //从结果集中一行获取数据
    int sid = rs.getInt("sid");
    String sname = rs.getString("sname");
    String sclass = rs.getString("sclass");

    //将结果添加到对象中
    stu.setSid(sid);
    stu.setSname(sname);
    stu.setSclass(sclass);

    //将对象添加到List集合中
    list.add(stu);
}

抽取工具类

因为每次获取数据库的连接对象比较麻烦,且加载驱动的操作只需执行一次,所以封装一个工具类专门用于获取Connection连接对象

工具类实现

/**
 * JDBC工具类
 *   1、获取数据库连接对象 Connection
 *   2、关闭资源
 */
public class JDBCUtils {
    private static final String DRIVER = "com.mysql.jdbc.Driver";
    private static final String URL = "jdbc:mysql:///java?useSSL=false";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "root";
    static {
        try {
            Class.forName(DRIVER);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //获取Connection对象
    public static Connection getConnetion() {
        Connection conn = null;
        try {
             conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
    //关闭资源
    public static void close(Connection conn , Statement stat,ResultSet rs) {
            try {
                if(conn != null) {
                    conn.close();
                }
                if(rs != null) {
                    rs.close();
                }
                if(stat != null) {
                    stat.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
    }
}

使用工具类

public class JDBCDemo1 {
    public static void main(String[] args) {
        Connection conn  = null;
        Statement stat = null;
        ResultSet rs = null;
        try {
            //2、获取Connection对象
            conn  = JDBCUtils.getConnetion();
            //3、获取Statement对象
            stat = conn.createStatement();
            //4、执行sql语句返回结果集
            rs = stat.executeQuery("select * from student where sid = 1");
            //5、处理结果集
            Student student = null;
            while(rs.next()) {
                student = new Student();
                student.setSid(rs.getInt("sid"));
                student.setSname(rs.getString("sname"));
                student.setSclass(rs.getString("sclass"));
            }
            System.out.println(student);

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //6、关闭资源
            JDBCUtils.close(conn, stat, rs);
        }
    }
}

JDBC实现登录

public class LoginDemo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名");
        String username = sc.nextLine();
        System.out.println("请输入密码");
        String password = sc.nextLine();
        Connection conn  = null;
        Statement stat = null;
        ResultSet rs = null;
        try {
            //2、获取Connection对象
            conn  = JDBCUtils.getConnetion();
            //3、获取Statement对象
            stat = conn.createStatement();
            //4、执行sql语句返回结果集
            //select * from tb_user where username = 'cxk' and password = '250' or 1 = 1;
            // xxxx' or 1 = '1
            String sql = "select * from tb_user where username = '" +username + "' and password = '" + password +"'";
            System.out.println(sql);
            rs = stat.executeQuery(sql);
            //5、处理结果集
            User user = null;
            while(rs.next()) {
                user = new User();
                user.setId(rs.getInt("id"));
                user.setUsername(rs.getString("username"));
                user.setPassword(rs.getString("password"));
            }
            if(user != null) {
                System.out.println("登录成功");
            }else {
                System.out.println("登录失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //6、关闭资源
            JDBCUtils.close(conn, stat, rs);
        }
    }
}

登录的问题

在使用Statement对象的时候的问题:
1、在拼接字符串的时候需要自己手动的加上引号
2、可能会出现SQL注入的问题
当 密码输入  xxxxx' or 1 = '1   那么这时,任意的密码都会被当做登录成功

PreparedStatement使用

public class LoginDemo2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名");
        String username = sc.nextLine();
        System.out.println("请输入密码");
        String password = sc.nextLine();
        Connection conn  = null;
        Statement stat = null;
        ResultSet rs = null;
        try {
            //2、获取Connection对象
            conn  = JDBCUtils.getConnetion();
            //3、获取PreparedStatement对象   预加载sql语句
            String sql = "select * from tb_user where username = ? and password = ?";
            PreparedStatement ps  = conn.prepareStatement(sql);
            //将占位符替换成指定的值   ? 表示占位符    下标从左往右 1 开始
            ps.setString(1, username);
            ps.setString(2, password);

            System.out.println(ps);
            //4、执行sql语句获取结果集
            rs = ps.executeQuery();

            //5、处理结果集
            User user = null;
            while(rs.next()) {
                user = new User();
                user.setId(rs.getInt("id"));
                user.setUsername(rs.getString("username"));
                user.setPassword(rs.getString("password"));
            }
            if(user != null) {
                System.out.println("登录成功");
            }else {
                System.out.println("登录失败");
            }            
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //6、关闭资源
            JDBCUtils.close(conn, stat, rs);
        }
    }
}

Statement和PreparedStatement区别

1、PreparedStatement是Statement的子接口
2、PreparedStatement可以实现预加载,在编写SQL语句的时候可以使用?号作为占位符且在传递参数的时候会自动加上引号。
3、PreparedStatement能防止SQL注入

所谓的预加载就是传入SQL语句的时机,Statement是在执行SQL语句的是传递SQL。PreparedStatement是在创建对象的时候就传递SQL,所以就称之为预加载,利用这个在写SQL语句的时候可以用?号作为占位符,然后再传递参数

上一篇下一篇

猜你喜欢

热点阅读