(重点)MySQL(入门篇24)自制数据库连接池(DateSource数据源)

数据库连接池和线程池类似,主要是,Connection 相当浪费时间和内存(比新建线程慢多了)

在这里插入图片描述

一、连接池的背景

1. jdbc的背景

(1)成立背景:每个数据库厂商都有自己的数据库驱动,为了实现我们可以方便地连接到到不同数据库,(比如你的账户信息在MySQL数据库,头像图片在Oracle数据库),
(2)jdbc定义:jdbc是一个接口规范,数据库驱动(Driver)由数据库厂商自己来完成。关系如图所示。
在这里插入图片描述
(3)回顾连接的步骤:启动Driver,连接获得connection,获取statement,使用statement,增删改,或者查询(获得resultSet)

2. jdbc链接池的概念:

**类似线程池:**一个容器,程序加载就自动生成几个Connection ,然后用的时候比较方便,而且用完了不是关闭Connection,而是归还。

3.为什么要使用连接池?

(1)连接数据库的Connection十分浪费资源,(比如获得connection连接需要 900 毫秒,获得statement只需30毫秒,获得 ResultSet只需要 3毫秒,)
(2)数据池技术:准备一些一些预先的资源,过来就连接准备好的预先的资源。
(3)增加同时执行SQL的数量:,你最高的statement总数为 (最高负载):Connection数 * 每个Connection产生的statement数

二、连接池的实现(不用框架)

1.myJdbcPool.java实现步骤

1.在static批量生产配置的Connection放到Victor里面(Victor线程安全)
2.在getConnection()方法里,

  • 1.在集合victors取出一个Connection,
  • 2.并使用动态代理技术修改close()方法,让其变成归还connection对象到集合里。
2.myJdbcPool.java 代码

import javax.sql.DataSource;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.*;
import java.util.Properties;
import java.util.Vector;
import java.util.logging.Logger;

/**
 * JdbcPool 数据池(数据源)
 * #### 一.myJdbcPool.java实现步骤
 * 1.在loadConfiguration()批量生产配置的Connection放到Victor里面(Victor线程安全)
 * 2.在getConnection()方法里,
 * * (1).在集合victors取出一个Connection,
 * *  (2).并使用[动态代理技术]()修改close()方法,让其变成归还connection对象到集合里。
 */
public class JdbcPool implements DataSource {
    public static Vector<Connection> victors = new Vector<>();

    /**
     * 1.在loadConfiguration()批量生产配置的Connection
     * 放到Victor里面(Victor线程安全)
     */
    private static void loadConfiguration() {
        try {
            String configPath = "jdbcPoolConf.properties";
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(configPath));
            Properties properties = new Properties();

            //将输入流的数据载入到Properties对象里,inputSteam都可以?
            properties.load(bufferedInputStream);
            //用properties对象获得配置文件的信息
            String url = properties.getProperty("url");
            String user = properties.getProperty("user");
            String password = properties.getProperty("password");
            int jdbcPoolInitSize = Integer.parseInt(properties.getProperty("jdbcPoolInitSize"));
            //驱动
            Class.forName(properties.getProperty("driver"));
            //如果没有初始化就初始化,
            if (victors.size() == 0){
                for (int i = 0; i < jdbcPoolInitSize; i++) {
                    Connection connection = DriverManager.getConnection(url,user,password);
                    System.out.println("日志--获取到链接:"+configPath);
                    victors.addElement(connection);
                }
            }
        } catch (Exception e) {
            System.out.println("日志--创建失败!");
            e.printStackTrace();
        }

    }

    /**
     *  * 2.在getConnection()方法里,
     *   (1).在集合victors取出一个Connection,
     *    (2).并使用[动态代理技术]()修改close()方法,
     *  让其变成归还connection对象到集合里。
     * @return Connection,close()被动态代理修改了
     *
     */
    @Override
    public  Connection getConnection()  {
        if (victors.size() == 0){
            JdbcPool.loadConfiguration();
        }
        if (victors.size() > 0){
            //取出一个 Connection,并给final?
            final Connection connection = victors.remove(0);
            //关键的动态代理技术,实现修改connection的close方法
            return (Connection) Proxy.newProxyInstance(JdbcPool.class.getClassLoader(), connection.getClass().getInterfaces(), new InvocationHandler(){
                @Override
                public Object invoke(Object proxy, Method method, Object[] args)
                        throws Throwable {
                    if(!method.getName().equals("close")){
                        return method.invoke(connection, args);
                    }else{
                        //如果调用的是Connection对象的close方法,就把conn还给数据库连接池
                        victors.addElement(connection);
                        System.out.println(connection + "被还给Connections数据库连接池了!!");
                        System.out.println("Connections数据库连接池大小为" + victors.size());
                        return null;
                    }
                }
            });
        }else {
            System.out.println("日志--链接超时!");
            return  null;
        }
    }
    public static void release(Connection connection, Statement statement,ResultSet resultSet){
        //先开后关
        if (resultSet != null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }




//===========================实现的方法========================


                               @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
}
3.配置文件

配置文件:jdbcPoolConf.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/bmft_blog?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC
user=root
password=123456
jdbcPoolInitSize=10

4.效果

Run:(每个人数据库不一样,测试类请自己书写一个,这里测试类就不展示了)
在这里插入图片描述

三、常用的开源数据库连接池

(这里列一个纲领,具体的搜索我的博客)

1,DBCP

并发量低下,性能不要适用于小型系统,Tomcat内置

2.C3P0

单线程,性能差,适用于小型系统

3.Druid(阿里巴巴)

最好用的数据库连接池,高性能,高并发,高拓展,分析监控设计,快速交互查询,高可用(遇到一些情况,冗机还能运行)

四、如何使用Tomcat配置数据连接池

(这里列一个纲领,具体的搜索我的博客)

五、JNDI技术简介

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

JarvanStack

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

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

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

打赏作者

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

抵扣说明:

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

余额充值