详解JDBC各个对象

文章目录

    • DriverManager
    • Connection
    • Statement
    • PreparedStatement
    • ResultSet
    • 案例
      • 案例一:JDBC控制事务
      • 案例二:SQL 注入错误演示

DriverManager

  • 概述:DriverManager 是驱动管理类

  • 作用

    • 获取数据库连接
    // 返回数据库连接的对象,url 是指定连接路径,user 是数据库用户名 password 是数据库密码
    static Connection getConnection(String url , String user , String password);
    
    • url 语法
    jdbc:mysql://IP地址(域名):端口号/数据库名称
    

    如果连接的是本机 MySQL 服务器,并且端口号默认则 url简写为:jdbc:mysql:///数据库名称>

  • 示例代码

    // 1、获取数据库连接对象-自行更换数据库用户名和密码
    Connection con = DriverManager.getConnection("jdbc:mysql:///test","root","root");
    

Connection

  • 概述:Connection 是数据库连接类

  • 作用

    • 获取执行 SQL 的对象
    方法 作用
    Statement createStatement(); 返回执行 SQL 对象
    PreparedStatement prepareStatement(String sql); 返回执行 SQL 对象,和上述对象有区别
    • 管理事务
    方法 作用 注意事项
    setAutoCommit(boolean autoCommit); 开启事务 方法参数设置为 false ,即开启事务,反之
    commit(); 提交事务 事务执行中未出现错误,执行提交
    rollback(); 回滚事务 事务执行中出现错误,执行回滚
  • 示例代码(这里只为演示,并无实际效果,具体看后续案例)

    // 1、获取数据库连接对象
    Connection con = DriverManager.getConnection("jdbc:mysql:///test","root","root");
    // 2、获取执行 SQL 对象
    Statement st = con.createStatement();
    // ? 后续会讲,看下去
    PreparedStatement pst = con.prepareStatement("SELECT * FROM account WHERE id = ?");
    
    // 1、开启事务
    con.setAutoCommit(false);
    // 2、提交事务
    con.commit();
    // 3、回滚事务
    con.rollback();
    

Statement

  • 概述:执行 SQL 的对象

  • 常用方法

    方法 作用
    boolean execute(String sql); 可以执行任意的 SQL 语句
    int executeUpdate(String sql); 执行 DML、DDL语句,返回值:影响的行数,>0 则代表执行成功
    ResultSet executeQuery(String sql); 执行 DQL 查询语句
  • 示例代码

    • 数据库代码
    -- 创建一个数据库
    CREATE DATABASE IF NOT EXISTS test CHARACTER SET utf8;
    -- 使用数据库
    USE test;
    -- 创建一个账户表
    CREATE TABLE account(
    	id INT PRIMARY KEY AUTO_INCREMENT,
        NAME VARCHAR(20),
        balance DOUBLE
    );
    -- 向账户表中添加数据
    INSERT INTO account(NAME , balance) VALUES('张三',1000),('李四',1000);
    
    -- 查询账户表
    SELECT * FROM account;
    
    • Java 代码
    public class Test1 {
        public static void main(String[] args) throws ClassNotFoundException, SQLException {
            // 1、注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2、获取数据库连接对象
            Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
            // 3、获取执行 SQL 对象
            Statement st = con.createStatement();
            // 4、定义 SQL 语句
            String sql1 = "SELECT * FROM account WHERE id = 2";
            String sql2 = "UPDATE account SET balance = balance - 500 WHERE id = 1";
            // 5、执行 SQL 语句
            boolean flag = st.execute(sql1);
            int lineNum = st.executeUpdate(sql2);
            ResultSet rs = st.executeQuery(sql1);
            // 6、输出结果
            System.out.println(flag + " " + lineNum);
    
            // 输出 ResultSet 结果集结果
            while(rs.next()){
                int id = rs.getInt(1);
                String name = rs.getString("name");
                double balance = rs.getDouble(3);
                System.out.println(id + "---" + name + "---" + balance);
            }
    
            // 7、释放资源
            st.close();
            con.close();
        }
    }
    

    运行结果:

    true 1

    2—李四—1000.0


PreparedStatement

  • 概述:执行 SQL 的对象(可以防止 SQL 注入)

    • 作用:PreparedStatement 可以防止 SQL 注入,并且效率更高
  • SQL 注入!!!

    • 问题:在拼接 SQL 时候,有一些 SQL 特殊的关键字参与字符串的拼接,会造成安全性问题?(在案例中演示什么问题)
    • 解决此问题:使用 PreparedStatement 对象来解决,预编译的 SQL 参数使用>作为占位符
  • 常用方法

    方法 作用 参数
    setXxx(参数1,参数2) 给 ?赋值,Xxx代表数据类型 参数1:?的位置编号(从1开始)
    参数2:赋给?的值
  • 示例代码(此对象如何使用)

    • 数据库代码
    -- 创建一个数据库
    CREATE DATABASE IF NOT EXISTS test CHARACTER SET utf8;
    -- 使用数据库
    USE test;
    -- 创建一个账户表
    CREATE TABLE account(
    	id INT PRIMARY KEY AUTO_INCREMENT,
        NAME VARCHAR(20),
        balance DOUBLE
    );
    -- 向账户表中添加数据
    INSERT INTO account(NAME , balance) VALUES('张三',1000),('李四',1000);
    
    -- 查询账户表
    SELECT * FROM account;
    
    • Java 代码
    public class Test2 {
        public static void main(String[] args) throws ClassNotFoundException, SQLException {
            // 1、注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2、获取数据库连接对象
            Connection con = DriverManager.getConnection("jdbc:mysql:///test", "root", "root");
            // 3、定义 SQL 语句,这里使用占位符 ?
            String sql = "UPDATE account SET balance = balance - ? WHERE id = ?";
            // 4、创建 执行 SQL 对象
            PreparedStatement pst = con.prepareStatement(sql);
            // 5、设置参数,给第一个?设置值为 500 给第二个?设置值为 1
            pst.setInt(1,500);
            pst.setInt(2,1);
            // 6、执行 SQL 语句
            int lineNum = pst.executeUpdate();
            // 7、输出结果
            System.out.println(lineNum);
            // 8、释放资源
            pst.close();
            con.close();;
        }
    }
    

    运行后,可看到控制台输出结果 1 ,数据库中编号 1 的balance 变成了 500


ResultSet

  • 概述:结果集对象,用来封装查询结果的

  • 常用方法

    方法 作用 注意事项
    boolean next(); 游标向下移动一行,判断当前行是否有数据 有数据返回 true 无数据返回 false
    getXxx(参数); 获取数据 Xxx:代表数据类型
    参数是 int 类型,代表列的编号(从1开始),
    参数是 String 类型,代表列名称
  • 代码示例

    ResultSet rs = st.executeQuery(sql1);
    //循环判断游标是否是最后一行末尾。
    while(rs.next()){
        //获取数据
        int id = rs.getInt(1);
        String name = rs.getString("name");
        double balance = rs.getDouble(3);
        System.out.println(id + "---" + name + "---" + balance);
    }
    

案例

案例一:JDBC控制事务

  • 概述:事务,一个包含多个步骤的业务操作。如果这个业务操作被事务管理,多个步骤要么同时成功,要么同时失败。

  • 操作事务的三个步骤

    • 开始事务
    • 提交事务
    • 回滚事务
  • 代码示例(这里有很多的写法并不严谨,只是为了更好的演示效果,数据库还是上述步骤中用到过的)

    public class Test3 {
        public static void main(String[] args) {
            // 这里为了省事,简单这样写
            String url = "jdbc:mysql://localhost:3306/test";
            String user = "root";
            String password = "root";
            Connection con = null;
            PreparedStatement pst1 = null;
            PreparedStatement pst2 = null;
            try {
                // 1、注册驱动
                Class.forName("com.mysql.cj.jdbc.Driver");
                // 2、获取数据库连接
                con = DriverManager.getConnection(url,user,password);
                // 3、开启事务
                con.setAutoCommit(false);
                // 4、定义 SQL 语句,sql1 张三-500 sql2 李四+500
                String sql1 = "UPDATE account SET balance = balance - ? WHERE id = ?";
                String sql2 = "UPDATE account SET balance = balance + ? WHERE id = ?";
                // 5、获取执行 SQL 对象
                pst1 = con.prepareStatement(sql1);
                pst2 = con.prepareStatement(sql2);
                // 6、设置 占位符值
                pst1.setInt(1,500);
                pst1.setInt(2,1);
                pst2.setInt(1,500);
                pst2.setInt(2,2);
                // 7、执行 SQL
                pst1.executeUpdate();
    
                // 手动制造异常,可以运行次后,看下数据库的数字,再注释掉这行再运行,再看数据库数字
                int i = 3/0;
    
                pst2.executeUpdate();
    
                // 提交事务,因为遇见异常,所以这步代码并不执行
                con.commit();
            } catch (Exception e) {
                try{
                    if(con != null){
                        // 事务回滚,当 con 不为空的时候,才回滚
                        con.rollback();
                    }
                }catch (SQLException e1){
                    e1.printStackTrace();
                }
                e.printStackTrace();
            } finally {
                try {
                    // 释放资源
                    pst1.close();
                    pst2.close();
                    con.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

案例二:SQL 注入错误演示

  • 概述:SQL 语句拼接时,用一些特殊的关键字参与字符串拼接,会造成安全性问题

  • 代码示例

    • 数据库代码
    -- 创建数据库
    CREATE DATABASE IF NOT EXISTS test CHARACTER SET utf8;
    
    -- 创建 user 表
    CREATE TABLE USER(
    	username VARCHAR(20),		-- 用户名
    	PASSWORD VARCHAR(20)		-- 密码
    );
    
    -- 插入数据
    INSERT INTO USER VALUES('lisi',"a'or'a'='a");
    
    -- 查询数据,可发现下边 3行都会显示此条信息,这样错误太明显了,这是为什么?
    SELECT * FROM USER WHERE username = 'lisi' AND PASSWORD = 'a'OR'a'='a';
    
    SELECT * FROM USER WHERE username = 'fhdsjkf' AND PASSWORD = 'a' OR 'a' = 'a';
    
    SELECT * FROM USER WHERE username = 'a' AND PASSWORD = 'a' OR 'a' = 'a';
    

    注意:为什么上述3行都能显示呢?看下边两个框,可以知道,查询语句的条件有两个,中间又用 OR ,根据或的特性,只要满足其一即可,第二个红框,很明显一直是对的,所以就能查询出来。

你可能感兴趣的:(Java,基础知识专栏,数据库,sql,java,mysql,sql注入)