• JDBC详解—有图有真相


    一_JDBC概述

    1. JDBC是什么
          英文全称:Java DataBase Connectivity
          中文全称:Java 数据库连接技术

    2. JDBC的作用
         与数据库建立连接并对数据库执行操作:增删改查操作

    3. JDBC的组成
         由一组官方定义的接口(规范)组成:接口的实现类由数据库厂商提供:数据库驱动(包含实现操作数据库接口的类)

    4. JDBC的好处
        代码不依赖于任何数据库。
        只需要修改少量配置就可以方便切换到其他厂商数据库。

    02_JDBC核心API概述

    JDBC核心类和接口

    说明

    Connection 接口

    连接对象

    作用:与数据库建立连接并形成数据传输通道

    Statement 接口

    SQL语句发送对象

    作用:将SQL语句发送给数据库执行并获得执行结果

    ResultSet 接口

    结果集对象

    作用:用来封装满足查询条件的记录信息

    Drvier 接口 数据库驱动对象

     

     

     

     

     

     

     

     

    三_JDBC之注册驱动

    示例代码

    import com.mysql.jdbc.Driver;
    
    import java.sql.DriverManager;
    
    /**
      目标:
         1. 理解注册驱动的作用:告诉JVM接下来要操作哪个厂商的数据库了
         2. 掌握注册驱动的方式
         
        DriverManger工具类与注册驱动相关的方法
            * static registerDriver(Driver driver)
            * 注册数据库驱动
            * 存在问题:驱动会被注册两次
     */
    public class Demo01 {
        public static void main(String[] args) throws Exception{
            // 方式1:存在问题:驱动会被注册两次
            // 创建驱动对象(Driver是mysql厂商提供Driver接口的实现类)
            /*Driver driver = new Driver();
            // 注册驱动
            DriverManager.registerDriver(driver);*/
    
            // 方式二:利用反射触发Driver实现类的加载实现驱动注册
            Class.forName("com.mysql.jdbc.Driver");
        }
    }

    注册驱动的作用:告诉JVM接下来要操作哪个厂商的数据库了

    注册驱动方法 说明
    static registerDriver(Driver driver) 驱动会注册两次
    Class.forName("com.mysql.jdbc.Driver") 只会注册一次

    四_JDBC之获取连接对象

    示例代码

    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.util.Properties;
    
    /**
       目标:与数据库建立连接并获得Connection对象
    
       DriverManager工具类与获得连接对象相关的方法
        * static Connection    getConnection(String url, String user, String password)
            * 与数据库建立连接并返回连接对象
            * url: 数据库连接字符串
            * user:  用户名 root
            * password: 密码 root
    
        * static Connection    getConnection(String url, Properties info)
            * 与数据库建立连接并返回连接对象
            * url: 数据库连接字符串
            * info: 属性集合(双列集合,用法和map一样):用来存储用户名和密码
                * 可以将用户名和密码配置在文件中
    
    
        数据库连接字符串格式:
            完整格式:JDBC协议:子协议://数据库服务器地址:端口号/数据库名
                * JDBC协议:固定值是:jdbc
                * 子协议:一般是数据库厂商的名字,比如mysql或oracle
            省略格式:JDBC协议:子协议:/// 数据库名
                * 前提条件:操作本机数据库且端口号是默认值3306
    
    
        MySQL数据库连接字符串完整格式:jdbc:mysql://localhost:3306/day11
        MySQL数据库连接字符串省略格式:jdbc:mysql:///day11
    
     */
    public class Demo01 {
        public static void main(String[] args) throws Exception{
            // 方式1: 获得连接对象
            // test01();
    
            // 方式2:获得连接对象
            test02();
    
        }
    
        /**
         * 获得连接对象
         */
        private static void test02() throws Exception {
            // 1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2. 创建属性集对象
            // 键和值都是String类型
            Properties info = new Properties();
            // 创建输入流关联配置文件
            InputStream in = Demo01.class.getResourceAsStream("/jdbc.properties");
            // 从文件中加载数据到集合中
            info.load(in);
            System.out.println(info);// {user=root, password=root}
            /*info.setProperty("user", "root");
            info.setProperty("password", "root");*/
    
            // 2. 获得连接对象
            Connection conn = DriverManager.getConnection("jdbc:mysql:///day11", info);
            System.out.println(conn);
        }
    
        /**
         *  获得连接对象
         */
        private static void test01() throws Exception{
            // 1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2. 获得连接对象
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "root");
            System.out.println(conn);
        }
    }

    小结

    DriverManager类与数据库建立连接的方法 说明
    static Connection getConnetion( String url, String username, String password) 获得连接对象 url:连接字符串 username:用户名 password:密码
    static Connection getConnection( String url, Properties info) 获得连接对象

    五_JDBC之Statement对象概述

    • Statement对象的作用:将SQL语句发送给数据库执行并获取结果

    • 如何获得Statement对象:通过连接对象的方法获得:Statement createStatement();

    Statement对象常用方法 说明
    boolean execute(String sql) 可以执行任意SQL语句 一般用来执行DDL语句:创库或创表
    int executeUpdate(String sql) 用于执行增删改语句:返回影响的行数 只要不是查询都称为更新操作
    ResultSet executeQuery(String sql) 用于执行查询语句

    06_JDBC之执行DDL语句_创建表

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.Statement;
    
    /**
        目标:使用JDBC在MySQL的数据库中创建一张学生表
         1)    id 是主键,整数类型,自增长
         2)    name 是varchar(20),非空
         3)    性别 是char类型
         4)    生日 是date类型
     */
    public class Demo01 {
        public static void main(String[] args) throws Exception{
            // 1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2. 获得连接对象
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "root");
            // 3. 获得SQL语句发送对象
            Statement stmt = conn.createStatement();
            // 4. 准备SQL语句
            String sql = "create table student(" +
                    "id int primary key auto_increment," +
                    "name varchar(20) not null," +
                    "gender char(1)," +
                    "birthday date);";
            // 5. 调用发送对象的方法执行SQL
            stmt.execute(sql);
            // 6. 释放资源
            stmt.close();
            conn.close();
        }
    }

    小结

    使用JDBC在数据库创建数据表的步骤
      1. 注册驱动:Class.forName("驱动类全名字符串");
      2. 获得连接对象:Connection conn = DriverManger.getConnection("连接字符串","用户名","密码");
      3. 获得SQL语句发送对象:Statement stmt = conn.createStatement();
      4. 准备SQL语句:String sql="....";
      5. 调用SQL语句发送对象的方法:stmt.execute...(sql);
      6. 关闭连接释放资源

    07_JDBC之执行DML语句_增删改

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.Statement;
    
    /**
      目标:使用JDBC实现增删改功能
     */
    public class Demo01 {
        public static void main(String[] args) throws Exception{
            // 插入数据
            // testInsert();
    
            // 更新数据
            // testUpdate();
    
            // 删除数据
            testDelete();
        }
    
    
        // 插入数据
        public static void testInsert()throws Exception{
            // 1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2. 获得连接对象
            Connection conn = DriverManager.getConnection("jdbc:mysql:///day11", "root", "root");
            // 3. 获得SQL语句发送对象
            Statement stmt = conn.createStatement();
            // 4. 准备SQL语句
            String sql = "insert into student values(null,'rose','女','2000-12-20'),(null,'luck','男','1990-02-21');";
            // 5. 调用SQL语句发送对象的方法
            int row = stmt.executeUpdate(sql);
            System.out.println("row = " + row);
            // 6. 关闭连接释放资源
            stmt.close();
            conn.close();
        }
    
        // 修改数据:将id为3的学生性别修改为女,姓名修改为:lily
        public static void testUpdate()throws Exception{
            // 1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2. 获得连接对象
            Connection conn = DriverManager.getConnection("jdbc:mysql:///day11", "root", "root");
            // 3. 获得SQL语句发送对象
            Statement stmt = conn.createStatement();
            // 4. 准备SQL语句
            String sql = "update student set gender = '女', name='lily' where id = 3;";
            // 5. 调用SQL语句发送对象的方法
            int row = stmt.executeUpdate(sql);
            System.out.println("row = " + row); // 1
            // 6. 关闭连接释放资源
            stmt.close();
            conn.close();
        }
    
        // 删除数据:把id为2的学生删除
        public static void testDelete() throws Exception{
            // 1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2. 获得连接对象
            Connection conn = DriverManager.getConnection("jdbc:mysql:///day11", "root", "root");
            // 3. 获得SQL语句发送对象
            Statement stmt = conn.createStatement();
            // 4. 准备SQL语句
            String sql = "delete from student where id = 2";
            // 5. 调用SQL语句发送对象的方法
            int row = stmt.executeUpdate(sql);
            System.out.println("row = " + row); // 1
            // 6. 关闭连接释放资源
            stmt.close();
            conn.close();
        }
    }

    小结

    使用JDBC在数据库创建数据表的步骤
      1. 注册驱动:Class.forName("驱动类全名字符串");
      2. 获得连接对象:Connection conn = DriverManger.getConnection("连接字符串","用户名","密码");
      3. 获得SQL语句发送对象:Statement stmt = conn.createStatement();
      4. 准备SQL语句:String sql="....";
      5. 调用SQL语句发送对象的方法:stmt.execute...(sql);
      6. 关闭连接释放资源

    八.JDBC之ResultSet对象概述

    ResultSet原理图

    小结

    • ResultSet对象的作用:封装满足查询条件的记录信息

    • 如何获得ResultSet对象:通过Statement对象的方法获取:ResultSet executeQuery(String sql)

    ResultSet对象常用方法 说明
    boolean next() 将指针下移一行并判断当前位置是否有记录 有则返回true,否则返回false
    Xxx getXxx(列号或列名) 根据列号或列名获得当前行指定列的数据

    九.JDBC之执行DQL语句_查询数据

    示例代码

    import java.sql.*;
    
    /**
      目标:使用JDBC实现查询功能
      需求:查询所有学生信息并输出到控制台
    
      注意事项:
          1. 当指针执行结果集的第一行之前,调用了getXxx方法获取数据则会出现下面异常:
            java.sql.SQLException: Before start of result set
          2. 当指针执行结果集的最后一行之后,调用了getXxx方法获取数据则会出现下面异常:
            java.sql.SQLException: After end of result set
     */
    public class Demo01 {
        public static void main(String[] args) throws Exception {
            // 1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2. 获得连接对象
            Connection conn = DriverManager.getConnection("jdbc:mysql:///day11", "root", "root");
            // 3. 获得SQL语句发送对象
            Statement stmt = conn.createStatement();
            // 4. 准备SQL语句
            String sql = "select * from  student";
            // 5. 执行SQL语句并获得结果集对象
            ResultSet rs = stmt.executeQuery(sql);
    
            // 循环获取每一行数据
            // 将指针下移一行、
            while(rs.next()){
                // 根据列号获取每一列的值
               /* int id = rs.getInt(1);
                String name = rs.getString(2);
                String gender = rs.getString(3);
                String birthday = rs.getString(4);*/
    
                // 根据列名获取每一列的值
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String gender = rs.getString("gender");
                Date birthday = rs.getDate("birthday");
    
                System.out.println(id+","+name+","+gender+"," + birthday);
            }
    
            // 6. 关闭连接释放资源
            rs.close();
            stmt.close();
            conn.close();
        }
    }

    十.JDBC事务-转账案例

    • 需求:jack 给 rose 转账 500

    • 准备数据:创建账号表和添加用户数据

    • 步骤分析

    1. 注册驱动
    2. 获得连接对象并开启事务
    3. 获取SQL发送对象
    4. 准备扣钱SQL语句
    5. 执行扣钱SQL语句
    6. 准备加钱SQL语句
    7. 执行加钱SQL语句
    8. 如果没有问题则提交事务,否则回滚事务
    9. 关闭资源
    

      

    示例代码

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    /**
      目标:使用JDBC实现事务管理
      需求:Jack给rose转500块
    
      实现步骤
        1. 注册驱动
        2. 获得连接对象
        3. 获取SQL发送对象
        4. 准备扣钱SQL语句
        5. 执行扣钱SQL语句
        6. 准备加钱SQL语句
        7. 执行加钱SQL语句
        8. 关闭资源
    
      Connection对象与事务管理相关的方法
        * void setAutoCommit(boolean b)
            * 设置是否自动提交事务
            * b:true 自动提交,默认值
            * b:false 禁止自动提交 ==> 相当于start transaction;手动开启事务
        * void commit();
            * 提交事务
        * void rollback();
            * 回滚事务
     */
    public class Demo01 {
        public static void main(String[] args){
            // 声明连接对象
            Connection conn = null;
            Statement stmt = null;
            try{
               // 1. 注册驱动
               Class.forName("com.mysql.jdbc.Driver");
               // 2. 获得连接对象
               conn = DriverManager.getConnection("jdbc:mysql:///day11", "root", "root");
    
               // 开启事务:等价start transaction;
               conn.setAutoCommit(false);
    
               // 3. 获取SQL发送对象
               stmt = conn.createStatement();
               // 4. 准备扣钱SQL语句
               String sql01 = "update account set balance = balance - 500 where id = 1";
               // 5. 执行扣钱SQL语句
               int row = stmt.executeUpdate(sql01);
               System.out.println("扣钱:" + row);
    
               // 模拟异常
               System.out.println(10/0);
    
               // 6. 准备加钱SQL语句
               String sql02 = "update account set balance = balance + 500 where id = 2";
               // 7. 执行加钱SQL语句
               row = stmt.executeUpdate(sql02);
               System.out.println("加钱:" + row);
               // 提交事务
               conn.commit();
           } catch(Exception e){
               System.out.println("回滚了事务...");
                try {
                    if (conn != null)
                        conn.rollback(); // 回滚事务
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
            } finally {
                // 8. 关闭资源
                if (stmt != null){
                    try {
                        stmt.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
                if (conn !=null) {
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    小结

    Connection接口中与事务相关的方法 说明
    void setAutCommit(boolean b);
    设置是否自动提交事务,默认是true:自动提交 false:禁止自动提交,需要手动提交
    void commit() 提交事务
    void rollback() 回滚事务

    十一.创建JDBC工具类

    import java.sql.*;
    
    /**
     创建工具类的目的:将重复的代码定义到某个类的方法中,直接调用方法,可以简化代码。
     实现工具类的步骤
     1. 将固定字符串定义为常量
     2. 在静态代码块中注册驱动(只注册一次)
     3. 提供一个获取连接的方法:static Connection getConnection();
     4. 定义关闭资源的方法:close(Connection conn, Statement stmt, ResultSet rs)
     5. 重载关闭方法:close(Connection conn, Statement stmt)
     */
    public class JDBCUtil {
    
        // 1. 将固定字符串定义为常量
        private static final String DRIVER_CLASS = "com.mysql.jdbc.Driver";
        private static final String URL = "jdbc:mysql:///day11";
        private static final String USER = "root";
        private static final String PASSWORD = "root";
    
        /**
         * 2. 在静态代码块中注册驱动(只注册一次)
         */
        static {
            try {
                // 1. 注册驱动
                Class.forName(DRIVER_CLASS);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        /*
        * 3. 提供一个获取连接的方法:static Connection getConnection();
        * */
        public static Connection getConnection() {
    
          try{
              return DriverManager.getConnection(URL, USER,PASSWORD);
          } catch(Exception e){
              // return null;
              // 将编译时异常包装成运行时异常
              throw new RuntimeException(e);
          }
        }
    
        // 4. 定义关闭资源的方法:close(Connection conn, Statement stmt, ResultSet rs)
        public static void close(Connection conn, Statement stmt, ResultSet rs){
            /**
             关闭资源注意事项:先开后关(先创建的后关闭)
             1. 创建顺序:Connection ==> Statement ==> ResultSet
             2. 关闭顺序:ResultSet ==> Statement ==> Connectio
             */
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (stmt != null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn !=null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    
        //  5. 重载关闭方法:close(Connection conn, Statement stmt)
        public static void close(Connection conn, Statement stmt){
            close(conn, stmt, null);
        }
    }

    12.JDBC实现登录案例

    案例需求

      模拟用户输入账号和密码登录网站

      输入正确的账号,密码,显示登录成功

      输入错误的账号,密码,显示登录失败

    示例代码

    1、准备数据表和用户数据

    create table user(
        id int primary key auto_increment,
        username varchar(20) not null unique,
        password varchar(20) not null
    );
    insert into user(username,password)  values('jack','rose'),('rose','laowang');
    select * from user;
    
    select * from user where username = 'jack' and password = 'rose';

    2、实现登录

    import com.pkx._07utlis.JDBCUtil;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.Scanner;
    
    /**
     * 目标:实现用户登录
    
        实现步骤:
            1. 创建键盘录入对象:Scanner
            2. 接收用户名和密码
            3. 获得连接对象
            4. 获得SQL语句发送对象
            5. 准备要执行的SQL语句:登录SQL
            6. 执行查询语句获得结果集对象
            7. 判断是否登录成功
            8. 释放资源
     */
    public class LoginDemo {
        public static void main(String[] args) throws Exception{
            // 1. 创建键盘录入对象:Scanner
            Scanner sc = new Scanner(System.in);
            // 2. 接收用户名和密码
            System.out.println("请输入用户名:"); // jack
            String username = sc.nextLine();
            System.out.println("请输入密码:");  // rose
            String password = sc.nextLine();
    
            // 3. 获得连接对象
            Connection conn = JDBCUtil.getConnection();
            // 4. 获得SQL语句发送对象
            Statement stmt = conn.createStatement();
            // 5. 准备要执行的SQL语句:登录SQL
            String sql = "select * from user where username = '"+username+"' and password = '"+password+"';";
            System.out.println("sql = " +sql);
            // 6. 执行查询语句获得结果集对象
            ResultSet rs = stmt.executeQuery(sql);
            // 7. 判断是否登录成功
            if (rs.next()){
                System.out.println("欢迎你:" +username);
            } else {
                System.out.println("用户名或密码错误");
            }
            // 8. 释放资源
            JDBCUtil.close(conn, stmt, rs);
        }
    }

    十三.SQL注入概述和演示

    当我们输入以下密码,我们发现账号和密码都不对竟然登录成功了

    请输入用户名:
    hehe
    请输入密码:
    a' or '1'='1

    问题分析

    // 代码中的SQL语句
    "SELECT * FROM user WHERE name='" + name + "' AND password='" + password + "';";
    // 将用户输入的账号密码拼接后
    "SELECT * FROM user WHERE name='hehe' AND password='a' or '1'='1';"

    小结

    什么是SQL注入:用户输入的内容和SQL语句进行了拼接,用户输入的内容作为了SQL语法的一部分,改变了原有SQL语句的含义

    十四.PreparedStatement接口概述

    • PreparedStatement接口的继承体系:继承Statement

    • PreparedStatement对象的作用:用来发送SQL语句到数据库执行增删改查操作

    • 如何PreparedStatement对象:通过连接对象的方法获取:PreparedStatement ps = conn.prepareStatement(String sql);

    PreparedStatement接口常用方法 说明
    int executeUpdate(); 执行DML语句 返回影响的行数
    ResultSet executeQuery(); 执行DQL语句 返回满足查询条件的结果集对象

    十五.PreparedStatement解决SQL注入

    需求:使用PreparedStatement改造登录案例解决SQL注入问题

    import com.pkx._07utlis.JDBCUtil;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.Scanner;
    
    /**
     *  目标:理解SQL注入的概念
    
        什么是SQL注入:用户输入的内容和SQL语句进行了拼接,用户输入的内容作为了SQL语法的一部分,改变了原有SQL语句的含义。
    
        如何解决SQL注入问题:用户输入的内容不要和SQL语句进行拼接,此时不能使用Statement来发送SQL,需要使用PreparedStatement
        来发送SQL语句到数据库执行了。
     sql = select * from user where username = 'jack' and password = 'a' or '1'='1';
    
      使用PreparedStatement解决SQL注入问题
     */
    public class LoginDemo02 {
        public static void main(String[] args) throws Exception{
            // 1. 创建键盘录入对象:Scanner
            Scanner sc = new Scanner(System.in);
            // 2. 接收用户名和密码
            System.out.println("请输入用户名:"); // jack
            String username = sc.nextLine();
            System.out.println("请输入密码:");  // rose
            String password = sc.nextLine();
    
            // 3. 获得连接对象
            Connection conn = JDBCUtil.getConnection();
            // 4. 准备要执行的SQL语句:登录SQL
            // 4.1 未知内容使用占位符?代替:用户名和密码就属于未知内容
            String sql = "select * from user where username = ? and password = ? ;";
            System.out.println("sql = " +sql);
            // 5. 获得预编译对象:PreparedStatement
            PreparedStatement ps = conn.prepareStatement(sql);
    
            // 5.1 使用真实数据替换占位符?:给占位符问号赋值具体内容
            // 参数1:占位符的索引值,默认是从1开始
            // 参数2:占位符问号赋值的具体内容
            ps.setString(1,username);
            ps.setString(2,password);
    
            // 6. 执行查询语句获得结果集对象
            ResultSet rs = ps.executeQuery();
            // 7. 判断是否登录成功:  a' or '1'='1
            if (rs.next()){
                System.out.println("欢迎你:" +username);
            } else {
                System.out.println("用户名或密码错误");
            }
            // 8. 释放资源
            JDBCUtil.close(conn, ps, rs);
        }
    }

    小结

    解决SQL注入问题的核心思想是:
      1. 用户输入的内容不要和SQL语句进行拼接
      2. 使用PreparedStateme对象执行SQL语句

    十六.PreparedStatement和Statement区别

    相同点:都可以对数据库执行增删改查操作。
    	
    不同点:
         1. PreparedStatement有预编译功能,Statement没有预编译功能。
         2. PreparedStatement有缓存功能(缓存SQL语句的编译结果),Statement没有缓存功能。
         3. PreparedStatement没有SQL注入,更安全,Statement有SQL注入,不安全。
    

      

    十七.连接池概述

    1. 什么是连接池
        一个负责创建和管理连接对象的容器(集合)
      
    2. 为什么需要使用连接池
        因为频繁的创建和销毁连接是很耗资源(内存资源和时间资源)的过程。
        使用连接池可以减少频繁创建和效率连接带来的系统开销。 从而提高访问数据库的效率
      
    3. 连接池的核心思想:连接复用
    
    4. 连接池规范:DataSource

    十八.C3P0连接池基本使用

    1. 配置文件模板:c3p0-config.xml

    <c3p0-config>
      <!-- 使用默认的配置读取连接池对象 -->
      <default-config>
          <!--  连接参数 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property>
        <property name="user">root</property>
        <property name="password">root</property>
        
        <!-- 连接池参数 -->
        <property name="initialPoolSize">5</property>
        <property name="maxPoolSize">10</property>
        <property name="checkoutTimeout">2000</property>
        <property name="maxIdleTime">1000</property>
      </default-config>
    
      <named-config name="pkxingc3p0"> 
        <!--  连接参数 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/day25</property>
        <property name="user">root</property>
        <property name="password">root</property>
        
        <!-- 连接池参数 -->
        <property name="initialPoolSize">5</property>
        <property name="maxPoolSize">15</property>
        <property name="checkoutTimeout">2000</property>
        <property name="maxIdleTime">1000</property>
      </named-config>
    </c3p0-config>

    2.示例代码

    import com.mchange.v2.c3p0.ComboPooledDataSource;
    import javax.sql.DataSource;
    import java.sql.Connection;

    public class Demo01 { public static void main(String[] args) throws Exception{ // 3. 创建连接池对象 // 使用默认配置创建 // DataSource ds = new ComboPooledDataSource(); // 使用命名配置创建 DataSource ds = new ComboPooledDataSource("pkxingc3p0"); // 循环从连接池中获取连接对象 for (int i = 0; i < 16; i++) { // 调用连接池对象的方法获得连接对象 Connection conn = ds.getConnection(); System.out.println(i+ "==>" +conn); // ...... if (i == 5){ // 关闭连接对象:不是真正的关闭,而是将连接对象放回连接池中等待复用。 conn.close(); } } } }

    C3P0连接池API介绍

    ComboPooledDataSource构造方法 说明
    ComboPooledDataSource() 使用默认的配置default-config创建数据源对象
    ComboPooledDataSource(命名配置) 使用命名的配置named-config创建数据源对象
    使用步骤
    1. 导入c3p0相关jar包
            2. 准备c3p0配置文件
                2.1 配置文件要求
                命名要求:c3p0-config.xml
                位置要求:在src目录下
                2.2 配置信息
                    数据库信息:
                        数据库驱动:com.mysql.jdbc.Driver
                        数据库地址: url
                        用户名: user
                        密码:password
                    连接池信息:
                        初始化连接数:5
                        最大连接数:10
                        最大等待时间:3000毫秒
                        最大空闲时间:3000毫秒
    
            3. 创建连接池对象
            4. 调用连接池对象的方法获得连接对象
            ......
            5. 关闭连接对象:不是真正的关闭,而是将连接对象放回连接池中等待复用。

    十九.DRUID连接池基本使用

    API介绍

    DruidDataSourceFactory类静态方法 说明
    public static DataSource createDataSource(Properties properties) 创建连接池对象

    我们可以看到DRUID连接池在创建的时候需要一个Properties对象来设置参数,所以我们使用properties文件来保存对应的参数。DRUID连接池的配置文件名称随便,建议放到src目录下面方便加载。druid.properties文件内容:

    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://127.0.0.1:3306/day25
    username=root
    password=root
    initialSize=5
    maxActive=10
    maxWait=3000
    maxIdle=6
    minIdle=3

    示例代码

    import com.alibaba.druid.pool.DruidDataSourceFactory;
    
    import javax.sql.DataSource;
    import java.io.InputStream;
    import java.sql.Connection;
    import java.util.Properties;
    
    /**
     * 目标:创建Druid连接池并从池中获得连接对象
     */
    public class Demo01 {
        public static void main(String[] args)throws Exception {
            // 1. 创建集合用来存储配置信息
            Properties info = new Properties();
            System.out.println(info);
            // 2. 加载配置文件信息到集合中
            // 2.1 获得与配置文件关联的输入流
            // InputStream in = Demo01.class.getResourceAsStream("/druid.properties");
            info.load(Demo01.class.getResourceAsStream("/druid.properties"));
            System.out.println(info);
            // 3. 创建连接池对象
            DataSource ds = DruidDataSourceFactory.createDataSource(info);
    
            // 4. 从连接池中获得连接对象
            for (int i = 0; i < 11; i++) {
                Connection conn = ds.getConnection();
                System.out.println(i+"===>"+conn);
                // .....
                if (i==5){
                    // 5. 关闭连接对象:不是真正关闭而是放回池中
                    conn.close();
                }
            }
    
        }
    }

    小结

    Druid连接池的使用步骤
        1. 导入相关jar
        2. 准备配置文件:xxx.properties
            2.1 配置数据库信息
            2.2 配置连接池信息
        3. 创建属性集对象:Properties
            3.1 加载配置文件信息到属性集对象中
        4. 通过Driud提供的工具类方法创建数据源对象
        5. 调用数据源对象的方法获得连接对象:getConnection
        ....
           6. 调用连接对象方法将连接对象关闭返回池中

    二十.连接池工具类

    数据源工具类代码

    import com.alibaba.druid.pool.DruidDataSourceFactory;
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    import com.pkx._11druid.Demo01;
    
    import javax.sql.DataSource;
    import java.sql.*;
    import java.util.Date;
    import java.util.Properties;
    
    /**
     数据源工具类实现步骤
     1)    创建私有静态数据源成员变量 DataSource ds
     2)    在静态代码块中创建连接池
         a)    创建属性集对象
         b)    从类路径下加载属性文件,得到输入流对象
         c)    通过工厂类创建一个数据源
     3)    创建公有的得到数据源的方法 getDataSource()
     4)    创建得到连接对象的方法 getConnection()
     5)    创建释放资源的方法 close(Connction conn, Statement stmt, ResultSet rs)
     */
    public class DataSourceUtil {
        //  1)    创建私有静态数据源成员变量 DataSource ds
        private static DataSource ds = null;
    
    
        // 2)    在静态代码块中创建连接池:只需要创建1个
        static {
           try{
               // a)    创建属性集对象
               Properties info = new Properties();
               // b)    从类路径下加载属性文件,得到输入流对象
               info.load(Demo01.class.getResourceAsStream("/druid.properties"));
               // c)    通过工厂类创建一个数据源
               ds = DruidDataSourceFactory.createDataSource(info);
           } catch(Exception e){
               e.printStackTrace();
           }
        }
    
        // 3)    创建公有的得到数据源的方法 getDataSource()
        public static DataSource getDataSource(){
            return ds;
        }
    
        // 4)    创建得到连接对象的方法 getConnection()
        public static Connection getConnection() {
            try{
                return ds.getConnection();
            } catch(Exception e){
                // 将编译时异常包装成运行时异常
                throw new RuntimeException(e);
            }
        }
    
        // 5. 定义关闭资源的方法:close(Connection conn, Statement stmt, ResultSet rs)
        public static void close(Connection conn, Statement stmt, ResultSet rs){
            /**
             关闭资源注意事项:先开后关(先创建的后关闭)
             1. 创建顺序:Connection ==> Statement ==> ResultSet
             2. 关闭顺序:ResultSet ==> Statement ==> Connectio
             */
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (stmt != null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn !=null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    
        //  重载关闭方法:close(Connection conn, Statement stmt)
        public static void close(Connection conn, Statement stmt){
            close(conn, stmt, null);
        }
    }

    测试类代码

    import com.alibaba.druid.pool.DruidDataSourceFactory;
    import com.pkx._11druid.Demo01;
    
    import javax.sql.DataSource;
    import java.sql.*;
    import java.util.Properties;
    
    /**
     数据源工具类的测试
     */
    public class DataSourceUtilDemo {
        public static void main(String[] args) throws Exception{
            // 获得连接对象
            Connection conn = DataSourceUtil.getConnection();
            // 获得预编译对象
            PreparedStatement ps = conn.prepareStatement("insert into student values(null,?,?,?)");
            // 给问号赋值
            ps.setString(1 ,"老王");
            ps.setString(2 ,"男");
            ps.setString(3 ,"2020-01-20");
    
            // 执行SQL语句
            int row = ps.executeUpdate();
            System.out.println(row);
            // 关闭资源
            DataSourceUtil.close(conn, ps);
        }
    }
    

      

    小结

    数据源工具类实现步骤
    1)	创建私有静态数据源成员变量 DataSource ds
    2)	在静态代码块中创建连接池
    	a)	创建属性集对象
    	b)	从类路径下加载属性文件,得到输入流对象
    	c)	通过工厂类创建一个数据源
    3)	创建公有的得到数据源的方法 getDataSource()
    4)	创建得到连接对象的方法 getConnection()
    5)	创建释放资源的方法 close(Connction conn, Statement stmt, ResultSet rs)
    

      

    JDBC就介绍到这里,如果有总结得不好的地方,欢迎指正!

  • 相关阅读:
    面向对象进阶
    初识面向对象
    模块和包
    day 17递归函数
    pip命令无法使用
    Python中的iteritems()和items()
    C# 截取字符串
    Python连接Mysql数据库
    【PYTHON】 Missing parentheses in call to 'print'
    javaScript中with函数用法实例分析
  • 原文地址:https://www.cnblogs.com/zwb-19981125/p/13709065.html
Copyright © 2020-2023  润新知