【MySQL】第6篇--连接池

本文介绍了SQL注入的概念及其危害,并展示了如何使用PreparedStatement进行预编译以防止SQL注入,提高了SQL执行效率和安全性。同时,探讨了数据库连接池的作用,以C3P0和Druid为例详细阐述了连接池的配置和使用,以提升数据库性能。最后,提到了动态代理作为方法增强的一种手段。
摘要由CSDN通过智能技术生成

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 = ?;

作用:

​ 降低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("当前功能正在维护....");
        }
    }

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

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);
    }

连接池

​ 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();将连接归还到连接池中

硬编码实现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(); // 归还连接


    }
配置文件实现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(); // 归还连接*/


    }

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);
//        }
    }

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);
    }

}

动态代理: 方法增强

设计模式: 23种
	java代码在编写时固定的格式
方法增强:
	继承
	装饰者模式
	动态代理★
装饰者模式:
   1.装饰者类和被装饰者类必须实现相同的接口,或继承同一个类
   2.在装饰者类必须要有被装饰者类的引用
   3.在装饰者类中对需要增强的方法进行增强
   4.在装饰者类中对不需要增强的方法调用原来的业务逻辑

动态代理的实现方式:
	基于接口的: Proxy (JDK提供的) ★
	基于子类的: Cglib (Spring)
装饰者模式
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);
    }
}

总结:

preparedStatement: 预编译语句执行者
	sql语句中如果出现变动的值,使用 ? 占位
	获取预编译语句执行者
	为sql语句中的占位符设置执行的值
连接池:
	存放很多连接的list集合
C3P0连接池: 
Druid连接池:
Druid连接池工具类:
动态代理:
	方法增强:
		继承
		装饰者模式
		动态代理 ★


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙和龚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值