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

作用:

​ 降低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连接池工具类:
动态代理:
	方法增强:
		继承
		装饰者模式
		动态代理 ★


猜你喜欢

转载自blog.csdn.net/qq_41250372/article/details/125462435
今日推荐