• 【MySQL】第6篇--连接池


    sql注入:

    ​ select * from user where username = ‘rose’ and password = ‘erterfre’ or ‘1’=‘1’

    ​ 概述:

    ​ sql注入指的是,用户输入的信息成为了sql语句的一部分.

    //获取语句执行者

    connection.createStatament();

    PreparedStatement: 预编译对象

    ​ 先将sql传递给数据库,将sql语句事先编译好,使用时直接赋真实的值,执行sql即可

    查询:
    	select * from user where id = 1;
    	select * from user where id = ?;
    
    • 1
    • 2
    • 3

    作用:

    ​ 降低mysql数据库的压力
    ​ 提高sql的执行效率: mysql数据库只会将相同的sql语句预编译一次
    ​ 提高安全性: 可以解决sql注入的风险

    使用步骤:

    ​ 1.编写预编译的sql
    ​ String sql = "select * from user where name=? and password=? ";
    ​ String sql = "insert into user values(null,?,?) ";
    ​ 2.创建预编译对象
    ​ PreparedStatement pst = conn.prepareStatement(sql);
    ​ 3.设置具体的参数
    ​ pst.setXXX(int a,XXX 值);
    ​ a: 第几个 ? (占位符)
    ​ XXX: 具体类型的值
    ​ 4.执行sql即可
    ​ ResultSet rs = pst.executeQuery(); // 执行查询,返回 resultSet
    ​ int i = pst.executeUpdate(); // 执行 增 删 改 返回的是影响的行数

    使用预编译对象完成用户登录
    
    public static void main(String[] args)  {
            try {
                Scanner scanner = new Scanner(System.in);
                //    1.提示用户输入用户名和密码
                System.out.println("请输入您的用户名:");
                String username = scanner.nextLine();
                System.out.println("请输入密码:");
                String password = scanner.nextLine();
                //	2.获取用户输入的用户名和密码
                //	3.使用JDBC查询数据库完成登录
                //a 从工具类中获取链接
                Connection conn = JDBCUtils.getConnection();
                //b.编写sql语句
                //String sql = "select * from user where username = '"+username+"'and password = '"+password+"'";
                String sql = "select * from user where username = ? and password = ? ";
                //c.获取语句执行者
                //Statement st = conn.createStatement();
                //获取预编译语句执行者
                PreparedStatement st = conn.prepareStatement(sql);
                //给占位符赋值
                st.setString(1,username);
                st.setString(2,password);
                //d.执行sql并返回结果
                ResultSet rs = st.executeQuery();
                //	e.判断执行结果
                if(rs.next()){
                    //登录成功
                    System.out.println("恭喜<"+ username+">登录成功");
                }else {
                    System.out.println("用户名或密码错误");
                }
                //f.释放资源
                JDBCUtils.close(rs,st,conn);
            } catch (SQLException e) {
                System.out.println("当前功能正在维护....");
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    使用预编译对象完成商品表的增删改查:

    public static void main(String[] args) throws Exception {
            //查询
            //select();
            //添加
            //insert();
            //删除
            //delete();
            //修改
            update();
    
        }
    
        /**
         * 将id为7的商品 名称改为椰子 价格改为1899
         */
        private static void update() throws SQLException {
            Connection conn = JDBCUtils.getConnection();
            String sql = "update product set price = ?,name=? where id = ?";
            PreparedStatement pst = conn.prepareStatement(sql);
            pst.setDouble(1,1899);
            pst.setString(2,"椰子");
            pst.setInt(3,7);
            int i = pst.executeUpdate();
            if (i>0){
                System.out.println("修改成功");
                JDBCUtils.close(pst,conn);
            }
        }
    
        /**
         * 删除id为8
         */
        private static void delete() throws SQLException {
            Connection conn = JDBCUtils.getConnection();
            String sql = "delete from product where id = ? ";
            PreparedStatement pst = conn.prepareStatement(sql);
            pst.setInt(1,9);
            int i = pst.executeUpdate();
            if (i>0){
                System.out.println("删除成功");
            }
            JDBCUtils.close(pst,conn);
    
        }
    
        /**
         * 添加
         */
        public static void insert() throws Exception {
            //使用工具类注册驱动获取连接
            Connection conn = JDBCUtils.getConnection();
            //3.编写sql语句
            String sql = "insert into product values(null,?,?)";
            //使用预编译对象
            PreparedStatement pst = conn.prepareStatement(sql);
            pst.setString(1,"椰子700");
            pst.setDouble(2,1899);
            //4.获取语句执行者
            //5.执行sql语句
            int i = pst.executeUpdate();
            //6.打印结果集
            System.out.println(i);
            //7.释放资源
            JDBCUtils.close(pst,conn);
    
    
        }
        /**
         * 查询
         */
        private static void select() throws Exception {
            Connection conn = JDBCUtils.getConnection();
            //3.编写sql语句
            String sql = "select * from product";
            //4.获取语句执行者 小货车
            Statement st = conn.createStatement();
            //5.执行sql语句  返回的是集合
            ResultSet rs = st.executeQuery(sql);
            //6.处理结果集    next():判断是否还有下一条数据
            while (rs.next()){
                int id = rs.getInt(1);
                String name = rs.getString(2);
                double price = rs.getDouble(3);
                System.out.println(id+":"+name+":"+price);
            }
            //7.释放资源
           JDBCUtils.close(rs,st,conn);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    连接池

    ​ Connection: 连接

    ​ List

    ​ 连接池本质上就是一个存放很多连接的list集合

    概述

    ​ 连接池是创建和管理数据库连接的缓冲池技术。连接池就是一个容器,连接池中保存了一些数据库连接,这些连接是可以重复使用的。

    API: 连接池规范

    ​ Java为数据库连接池提供了公共的接口(规范)

    ​ DataSource 接口:

    ​ getConnection(): 从连接池中获取连接的方法

    ​ close(): 将该连接归还给连接池

    开发常用连接池

    C3P0连接池

    C3P0是一个开源的连接池,Hibernate框架默认使用的就是C3P0连接池(SSH:Struts2 + Spring + Hibernate)

    SSM: SpringMVC + Spring + Mybatis (三大框架)

    ComboPooledDataSource : C3P0的连接池对象

    public ComboPooledDataSource()
    无参构造使用默认配置(使用xml中default‐config标签中对应的参数)
    
    public ComboPooledDataSource(String configName)
    有参构造使用命名配置(configName:xml中配置的名称,使用xml中named‐config标签中对应的参数)
    
    public Connection getConnection()
    从连接池中取出一个连接
    
    Connection:
    	conn.close();将连接归还到连接池中
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    硬编码实现c3p0:

     public static void main(String[] args) throws PropertyVetoException, SQLException {
            //0.导入c3p0连接池的jar包 (2个)
            //1.创建c3p0连接池对象
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            //2.设置连接的基本信息(driver,url,username,password)
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/94db1");
            dataSource.setUser("root");
            dataSource.setPassword("root");
            //3.设置连接池的基本信息
            dataSource.setInitialPoolSize(5); // 设置初始化连接数量
            dataSource.setMaxPoolSize(10); // 设置最大连接数量
            dataSource.setCheckoutTimeout(3000); // 设置最大等待时间
            dataSource.setMaxIdleTime(5000); // 设置最大空闲时间
            //4.使用连接池中的连接
            /*for (int i = 0; i < 11; i++) {
                Connection conn = dataSource.getConnection();
                System.out.println(conn);
                if(i==9){
                    // 将当前连接归还到连接池中
                    conn.close();
                }
            }*/
            //5.使用连接池中的连接操作数据库
            Connection conn = dataSource.getConnection();
            String sql = "select * from product ";
            PreparedStatement pst = conn.prepareStatement(sql);
            ResultSet rs = pst.executeQuery();
            while(rs.next()){
                System.out.println(rs.getInt(1)+" : "+
                    rs.getString(2)+" : "+
                    rs.getDouble(3)
                );
            }
            //6.释放资源
            rs.close();
            pst.close();
            conn.close(); // 归还连接
    
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    配置文件实现c3p0

    public static void main(String[] args) throws PropertyVetoException, SQLException {
            //0.导入c3p0连接池的jar包 (2个) 和 配置文件
            // c3p0连接池的配置文件名为: c3p0-config.xml (不能更改)
            // 配置文件存放在src目录下
            //1.创建c3p0连接池对象
            // 如果调用无参构造,c3p0会自动解析配置文件,使用配置文件中的默认配置信息
            // 如果调用有参构造,参数为配置文件中配置信息的名称
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            //4.使用连接池中的连接
            for (int i = 0; i < 9; i++) {
                Connection conn = dataSource.getConnection();
                System.out.println(conn);
    
            }
            //5.使用连接池中的连接操作数据库
           /* Connection conn = dataSource.getConnection();
            String sql = "select * from product ";
            PreparedStatement pst = conn.prepareStatement(sql);
            ResultSet rs = pst.executeQuery();
            while(rs.next()){
                System.out.println(rs.getInt(1)+" : "+
                    rs.getString(2)+" : "+
                    rs.getDouble(3)
                );
            }
            //6.释放资源
            rs.close();
            pst.close();
            conn.close(); // 归还连接*/
    
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    DRUID(德鲁伊)

    com.alibaba.druid.pool.DruidDataSourceFactory 类有创建连接池的方法

     public static void main(String[] args) throws Exception {
            //0.导入jar包(1个)和配置文件(properties)
            //1.使用Druid工厂创建 Druid连接池
            InputStream is = DruidDemo.class.getResourceAsStream("/druid.properties");
            Properties prop = new Properties();
            prop.load(is);
            DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
            Connection conn = dataSource.getConnection();
            String sql = "select * from product";
            PreparedStatement pst = conn.prepareStatement(sql);
            ResultSet rs = pst.executeQuery();
            while (rs.next()){
                int id = rs.getInt(1);
                String name = rs.getString(2);
                double price = rs.getDouble(3);
                System.out.println(id+":"+name+":"+price);
            }
            JDBCUtils.close(rs,pst,conn);
            //2.从连接池中获取连接
    //        for (int i = 0; i <11 ; i++) {
    //            Connection conn = dataSource.getConnection();
    //            System.out.println(conn);
    //        }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    DRUID工具类封装

     public class DruidPoolUtils {
        private static DataSource dataSource;
        static {
            //解析配置文件,让durid工厂根据配置文件创建druid连接池
            try {
                InputStream is = DruidPoolUtils.class.getResourceAsStream("/druid.properties");
                Properties prop = new Properties();
                prop.load(is);
                dataSource = DruidDataSourceFactory.createDataSource(prop);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        //获取连接池的方法
        public static DataSource getDataSource(){
            return dataSource;
        }
    
    
        //2.获取连接的方法
        public static Connection getConnection() throws Exception {
            return dataSource.getConnection();
        }
    
    
        //3.释放资源(归还链接)
        public static void close(ResultSet rs, Statement st,Connection conn){
            try {
                if (rs!=null){
                    rs.close();
                }
                if (st!=null){
                    st.close();
                }
                if (conn!=null){
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    //    重载方法
        public static void close(Statement st,Connection conn){
            close(null,st,conn);
        }
    }
    
    测试Druid工具类
    
    public class TestDruidDemo {
    
        public static void main(String[] args) throws Exception {
            //1.从连接池工具类中获取连接
            Connection conn = DruidPoolUtils.getConnection();
            //2.使用连接操作数据库
            String sql = "select * from product";
            PreparedStatement pst = conn.prepareStatement(sql);
            ResultSet rs = pst.executeQuery();
            while (rs.next()){
                int id = rs.getInt(1);
                String name = rs.getString(2);
                double price = rs.getDouble(3);
                System.out.println(id+":"+name+":"+price);
            }
            //3.归还连接
            DruidPoolUtils.close(rs,pst,conn);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    动态代理: 方法增强

    设计模式: 23种
    	java代码在编写时固定的格式
    方法增强:
    	继承
    	装饰者模式
    	动态代理★
    装饰者模式:
       1.装饰者类和被装饰者类必须实现相同的接口,或继承同一个类
       2.在装饰者类必须要有被装饰者类的引用
       3.在装饰者类中对需要增强的方法进行增强
       4.在装饰者类中对不需要增强的方法调用原来的业务逻辑
    
    动态代理的实现方式:
    	基于接口的: Proxy (JDK提供的) ★
    	基于子类的: Cglib (Spring)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    装饰者模式
    Car接口
    public interface Car {
    
        void run();
        void color();
        String jiaYou(String you);
    }
    QQ.java实现Car接口
    public class QQ implements Car {
        @Override
        public void run() {
            System.out.println("qq车以每秒一米的速度在挪动");
        }
    
        @Override
        public void color() {
            System.out.println("绿色的");
        }
    
        @Override
        public String jiaYou(String you) {
            return "qq车在加油"+you;
        }
    }
    QQWarpper.java实现Car接口
    public class QQWarpper implements Car {
    private QQ qq;
    
        public QQWarpper(QQ qq){
            this.qq = qq;
        }
        @Override
        public void run() {
            System.out.println("qq车以每秒1千米的速度在飞奔");
        }
    
        @Override
        public void color() {
            qq.color();
        }
    
        @Override
        public String jiaYou(String you) {
            return qq.jiaYou(you);
        }
    }
    
    测试 test.java
    public class Test {
        public static void main(String[] args) {
    
            QQ qq = new QQ();
            qq.color();
            qq.run();
            String you = qq.jiaYou("93#");
            System.out.println(you);
    
    
    //        QQWarpper warpper = new QQWarpper(new QQ());
    //        warpper.run();
    //        warpper.color();
    //        String you = warpper.jiaYou("93#");
    //        System.out.println(you);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    总结:

    preparedStatement: 预编译语句执行者
    	sql语句中如果出现变动的值,使用 ? 占位
    	获取预编译语句执行者
    	为sql语句中的占位符设置执行的值
    连接池:
    	存放很多连接的list集合
    C3P0连接池: 
    Druid连接池:
    Druid连接池工具类:
    动态代理:
    	方法增强:
    		继承
    		装饰者模式
    		动态代理 ★
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    计网 | 形象理解路由协议RIP、OSPF、BGP
    Linux云计算 |【第二阶段】NETWORK-DAY4
    ActiveState Platform - November 2022
    像素坐标和实际坐标的转换
    基于STM32F4系列的ETH IAP在线升级程序
    HTML静态网页作业——澳门英文旅游网站设计与实现HTML+CSS+JavaScript
    go语法速查手册
    CRC8校验算法源码——C语言版
    VPN(虚拟专用网)攻略大全,你一定会用到!
    【数据挖掘工程师-笔试】2022年海尔 公司
  • 原文地址:https://blog.csdn.net/qq_41250372/article/details/125462435