JavaWeb_Day06

JDBC

今日内容

1. JDBC基本概念
2. 快速入门
3. 对JDBC中各个接口和类的详解

JDBC

1. 概念:Java DataBase Connectivity java数据库连接,java语言操作数据库
   * JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,既接口。哥哥数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口JDBC编程,真正执行的代码是jar包中的实现类

2. 快速入门:
    * 步骤:
        1. 导入jar:mysql-connector-java-8.0.25.jar
           1. 复制mysql-connector-java-8.0.25.jar到lib下
           2. 右键-->add as Library
        2. 注册驱动
            Class.forName("com.mysql.jc.jdbc.Driver"); 
        3. 获取数据库连接对象Connection
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/DataBaseName?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC","root","1234"); 
        4. 定义SQL
            String sql = "update accout set balance = 500 where id = 1"; 
        5. 获取执行sql对象Statement
            Statement stmt = conn.createStatement();
        6. 执行sql ,接受返回的对象
            int count = stmt.executeUpdate(sql); 
        7. 处理结果
            System.out.println(count);
        8. 释放资源 
            stmt.close();
            conn.close();

3. 详解各个对象
    1. DriverManager: 驱动管理对象
        * 功能:
            1. 注册驱动:
                static void registerDriver(Driver driver):注册与给定的驱动程序
                写代码时:Class.forName("com.mysql.cj.jdbc.Driver");
                通过查看源码:发现在com.mysql.cj.jdbc.Driver类中有静态代码块:
                    static {
                        try {
                            java.sql.DriverManager.registerDriver(new Driver());
                        } catch (SQLException E) {
                            throw new RuntimeException("Can't register driver!");
                        }
                    }
                **注意**:mysql5之后注册驱动可以省略
            2. 获取数据库连接  
                * 方法:static Connection getConnection(String url,String user,String password)
               * 参数:
                   * url:指定连接的路径
                       * 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
                       * 例如:jdbc:mysql://localhost:3306/DataBaseName?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
                       * 细节:如果连接的是本地mysql数据库,且默认端口为3306,则url可以写为:jdbc:mysql:///数据库名称
                   * user:用户名
                   * password:密码 
    2. Connection:  数据库连接对象
        1. 功能:
            1. 获取执行sql的对象
                * Statement createStatement()
                * PrepareStatement prepareStatement(String sql)  
            2. 管理事务:
                * 开启事务:void setAutoCommit(boolean autoCommit):该方法设置参数为false,即开启事务
                * 提交事务:commit()
                * 回滚事务: rollback()
    3. Statement:  执行sql的对象
       1. 执行sql
            1. boolean execute(String sql): 可以执行任意的SQL语句
            2. int executeUpdate(String sql): 执行DML(insert,update,delete)语句,DDL(create,alter,drop)语句
                * 返回值:影响的行数  
            3. ResultSet executeQuery(String sql): 执行DQL(select)语句 
        2. 练习:
            1. accout表 添加一条记录
            2. account表 修改记录
            3. account表 删除一条记录  
    4. ResultSet:结果集对象,封装查询结果
       1. boolean next(): 右边向下移动一行,判读当前行是否是最后一行末尾,是否有数据,是false,不是true
       2.  getXxx(): 获取数据
            * Xxx代表数据类型   如:int getInt()  String  getString() 
                * int :代表列的编号,从1开始
                * String:代表列名称 
        * **注意**:
            * 使用步骤:
                1. 游标向下移动一行
                2. 判断是否有数据
                3. 获取数据  
    5. PreparedStatement:执行sql的对象   
        1. sql注入问题: 在拼接sql时有一些sql的特使关键字参与字符串的拼接,会造成安全问题
           1. 输入任意用户与密码 
           2. sql:select * from user where username = 'sss' and password = 'adsa' or 'a' = 'a' 
        2. 解决:使用PreparedStatement对象  
        3. 预编译sql:参数?做占位符 
           1. 步骤:
              1. 导入jar:mysql-connector-java-8.0.25.jar
              2. 注册驱动
              3. 获取数据库连接对象Connection
              4. 定义SQL
                * 注意:sql参数?做占位符 
                * 如:select * from user where username = ? and password = ?; 
              5. 获取执行sql对象PreparedStatement
                * 调用:Connevtion.prepareStatement(String sql)
              6. 给?赋值:
                 1. 方法:setXxx(参数1,参数2)
                    * 参数1:?的位置标号,从一开始
                    * 参数2:?的值   
              7. 执行sql ,接受返回的对象
              8. 处理结果
              9. 释放资源
            5. 注意:后期都用prepareStatement

抽取JDBC工具类 :JDBCUtils

* 目的:简化书写
* 分析:
    1. 注册驱动也抽取
    2. 抽取一个方法获取连接对象
        1. 需求:不想传递参数,还要保证工具类的通用性
        2. 解决:配置文件
            jdbc.properties 
                url=
                user=
                password=
    3. 抽取一个方法去释放资源

代码实现

        static {
        //读取资源文件
        try {
            //1.创建Properties集合类
            Properties pro = new Properties();
            //获取src下路径文件的方式 Classloader
            ClassLoader classLoader = JdbcUtils.class.getClassLoader();
            URL res =  classLoader.getResource("jdbc.properties");
            assert res != null;
            String path = res.getPath();
            System.out.println(path);
            //2.加载文件
            pro.load(new FileReader(path));
            //3.获取数据,赋值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //4.注册驱动
            Class.forName(driver);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
* 练习:
    * 需求:
        1. 通过键盘录入用户名和密码
        2. 判断用户是否登入成功
    * 步骤:
        1. 创建表 user
            CREATE table USER(
                id INT PRIMARY KEY AUTO_INCREMENT ,
                username VARCHAR (32),
                PASSWORD VARCHAR (32)
            ); 
            INSERT INTO user VALUES (NULL ,'zhangsan',"123");
            INSERT INTO user VALUES (NULL ,'lisi',"234");

代码

    public boolean login2(String username,String password){
        if (username == null && password == null){
            return false;
        }
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        //连接数据库来判断是否成功
        try {
            conn = JdbcUtils.getConnection();
            //定义SQL
            String sql = "select * from user where username = ? and PASSWORD = ?";
            //获取执行sql对象PreparedStatement
            pstmt = conn.prepareStatement(sql);
            //给?赋值
            pstmt.setString(1,username);
            pstmt.setString(2,password);
            //执行sql ,接受返回的对象
            rs = pstmt.executeQuery();
            //处理结果
            return rs.next();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            //释放资源
            JdbcUtils.close(rs,pstmt,conn);
        }
        return false;
    }
}

JDBC控制事务

1. 事务:一个包含多个步骤的业务操作。如果这个事务操作被事务管理,则这些步骤要么同时成功,要么同时失败
2. 操作:
   1. 开启事务
   2. 提交事务
   3. 回滚事务
3. 使用Connection对象来管理事务
   1. 开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false及开启事务
        * 在sql之前开启事务
   2. 提交事务:commit() :
        * 当所有sql都执行完提交事务 
   3. 回滚事务: rollback()
        * 在catch中回滚事务 

代码

    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;
        ResultSet rs = null;
        try {
            //获取连接
            conn = JdbcUtils.getConnection();
            //开起事务
            conn.setAutoCommit(false);
            //定义SQL
            String sql1 = "update account set balance = balance - ? where id = ?";
            String sql2 = "update account set balance = balance + ? where id = ?";
            assert false;
            //获取执行sql对象PreparedStatement
            pstmt1 = conn.prepareStatement(sql1);
            pstmt2 = conn.prepareStatement(sql2);
            //给?赋值
            pstmt1.setDouble(1, 500);
            pstmt1.setInt(2, 1);
            pstmt2.setDouble(1, 500);
            pstmt2.setInt(2, 2);
            //执行sql ,接受返回的对象
            pstmt1.executeUpdate();
            pstmt2.executeUpdate();
            //提交事务
            conn.commit();
        }catch (Exception e){
            //回滚事务
            try {
                if (conn != null){
                    conn.rollback();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }finally {
            JdbcUtils.close(null,pstmt1,conn);
            JdbcUtils.close(null,pstmt2,null);
        }
    }
上一篇:Day06-Scanner


下一篇:#LeetCode每日打卡 --- day06 [ LeetCode.3 无重复字符的最长子串 && LeetCode.567 字符串的排列 ]