MySQL池化框架学习接池自定义


Posted in MySQL onJuly 23, 2022

引言

最近在学习了通用池化框架commons-pool2实践之后,再HTTP性能测试中进行了实践,结果出乎意料,对于性能提升没啥卵用。经过我自己的本地测试,性能也是足够好的。

后来我仔细想了想,原来是我用错地方了。本来想自己写一个Redis的连接池的没想到,jedis的连接池本身就是commons-pool2开发的,让我有点意外,看来想的是一样的。commons-pool2用来做连接池是非常不错的。

我仔细找了找,发现还缺一个本地的MySQL连接池,而不是springboot那样需要启动一个服务才行。当然应该也是有的,不过我非常想自己写一个然后进行各类测试,所以也没有仔细找。

可池化对象

首先,我们需要一个可池化对象,这里我选用了com.funtester.db.mysql.FunMySql,这是一个我自己写的单链接的MySQL对象。我计划用这个作为基础可池化对象。

package com.funtester.db.mysql;
import com.funtester.base.interfaces.IMySqlBasic;
import com.funtester.config.SqlConstant;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
/**
 * mysql操作的基础类
 * <p>用于存储数据,多用于爬虫</p>
 */
public class FunMySql extends SqlBase implements IMySqlBasic {
    /**
     *  {@link SqlConstant#FUN_SQL_URL}会替换IP到URL
     */
    String url;
    /**
     * 库
     */
    String database;
    /**
     * 用户
     */
    String user;
    /**
     * 密码
     */
    String password;
    Connection connection;
    Statement statement;
    /**
     * 私有构造方法
     *
     * @param url      连接地址,包括端口
     * @param database 库
     * @param user     用户名
     * @param password 密码
     */
    public FunMySql(String url, String database, String user, String password) {
        this.url = url;
        this.database = database;
        this.user = user;
        this.password = password;
        getConnection(database);
    }
    /**
     * 初始化连接
     */
    @Override
    public void getConnection() {
        getConnection(EMPTY);
    }
    /**
     * 执行sql语句,非query语句,并不关闭连接
     *
     * @param sql
     */
    @Override
    public void executeUpdateSql(String sql) {
        SqlBase.executeUpdateSql(connection, statement, sql);
    }
    /**
     * 查询功能
     *
     * @param sql
     * @return
     */
    @Override
    public ResultSet executeQuerySql(String sql) {
        return SqlBase.executeQuerySql(connection, statement, sql);
    }
    /**
     * 关闭query连接
     */
    @Override
    public void over() {
        SqlBase.close(connection, statement);
    }
    @Override
    public void getConnection(String database) {
        if (connection == null)
            connection = SqlBase.getConnection(SqlConstant.FUN_SQL_URL.replace("ip", url).replace("database", database), user, password);
        if (statement == null) statement = SqlBase.getStatement(connection);
    }
}

池化工厂

相对连接,创建com.funtester.db.mysql.FunMySql的时候,顺便一起初始化MySQL连接。然后再com.funtester.db.mysql.MysqlPool.FunTester#destroyObject的时候进行连接的回收。

    /**
     * 池化工厂类
     */
    private class FunTester extends BasePooledObjectFactory<FunMySql> {
        @Override
        FunMySql create() throws Exception {
            return new FunMySql(url, database, user, password)
        }
        @Override
        PooledObject<FunMySql> wrap(FunMySql obj) {
            return new DefaultPooledObject<FunMySql>(obj)
        }
        @Override
        void destroyObject(PooledObject<FunMySql> p) throws Exception {
            p.getObject().over()
            super.destroyObject(p)
        }
    }

对象池

这里显得有些冗余,后面再使用过程中,我会继续优化。通过创建一个com.funtester.db.mysql.MysqlPool对象,获取一个com.funtester.db.mysql.FunMySql对象池。

/**
 * 自定义MySQL连接池对象
 */
class MysqlPool extends PoolConstant {
    private static final Logger logger = LogManager.getLogger(MysqlPool.class);
    /**
     * {@link com.funtester.config.SqlConstant#FUN_SQL_URL}会替换IP到URL*/
    String url;
    /**
     * 库
     **/
    String database;
    /**
     * 用户
     **/
    String user;
    /**
     * 密码
     **/
    String password;
    private GenericObjectPool<FunMySql> pool
    MysqlPool(String url, String database, String user, String password) {
        this.url = url
        this.database = database
        this.user = user
        this.password = password
        init()
    }
    /**
     * 初始化连接池
     * @return
     */
    def init() {
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxTotal(MAX);
        poolConfig.setMinIdle(MIN_IDLE);
        poolConfig.setMaxIdle(MAX_IDLE);
        poolConfig.setMaxWaitMillis(MAX_WAIT_TIME);
        poolConfig.setMinEvictableIdleTimeMillis(MAX_IDLE_TIME);
        pool = new GenericObjectPool<FunMySql>(new FunTester(), poolConfig);
    }
}

API封装

自从学习了Go语言的gorm框架和Redis框架,我发现其实不用把池化相关信息不用暴露出来,直接封装原始的API,暴露给用户使用,这样用户就不用关心连接的回收问题了。

    /**
     * 借出对象
     * @return
     */
    def borrow() {
        try {
            return pool.borrowObject()
        } catch (e) {
            logger.warn("获取${JSONObject.class} 失败", e)
        } finally {
            new JSONObject()
        }
    }
    /**
     * 归还对象
     * @param funMySql
     * @return
     */
    def back(FunMySql funMySql) {
        pool.returnObject(funMySql)
    }
    /**
     * 执行update SQL
     * @param sql
     * @return
     */
    def execute(def sql) {
        def driver = borrow()
        try {
            driver.executeUpdateSql(sql)
        } catch (e) {
            logger.warn("执行:{}失败", sql)
        } finally {
            back(driver)
        }
    }
    /**
     * 执行查询SQL
     * @param sql
     * @return
     */
    def query(def sql) {
        def driver = borrow()
        try {
            return driver.executeQuerySql(sql)
        } catch (e) {
            logger.warn("执行:{}失败", sql)
        } finally {
            back(driver)
        }
    }

以上就是MySQL连接池自定义示例详解的详细内容,更多关于MySQL连接池自定义的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
MySQL Innodb关键特性之插入缓冲(insert buffer)
Apr 08 MySQL
解决MySQL存储时间出现不一致的问题
Apr 28 MySQL
MySQL update set 和 and的区别
May 08 MySQL
mysql 8.0.24版本安装配置方法图文教程
May 12 MySQL
MySQL之PXC集群搭建的方法步骤
May 25 MySQL
MySQL里面的子查询的基本使用
Aug 02 MySQL
MySQL之select、distinct、limit的使用
Nov 11 MySQL
面试提问mysql一张表到底能存多少数据
Mar 13 MySQL
Mysql多层子查询示例代码(收藏夹案例)
Mar 31 MySQL
MySQL三种方式实现递归查询
Apr 18 MySQL
MySQL中EXPLAIN语句及用法
May 20 MySQL
MySQL数据库查询之多表查询总结
Aug 05 MySQL
mysql sock文件存储了什么信息
Jul 15 #MySQL
mysql sock 文件解析及作用讲解
Jul 15 #MySQL
mysqldump进行数据备份详解
Jul 15 #MySQL
MySQL的表级锁,行级锁,排它锁和共享锁
Jul 15 #MySQL
MySQL事务的隔离级别详情
Jul 15 #MySQL
MySQL事务的ACID特性以及并发问题方案
Jul 15 #MySQL
MySQL的意向共享锁、意向排它锁和死锁
Jul 15 #MySQL
You might like
一个简单计数器的源代码
2006/10/09 PHP
php mssql 日期出现中文字符的解决方法
2009/03/10 PHP
深入解析php中的foreach问题
2013/06/30 PHP
php获取图片信息的方法详解
2015/12/10 PHP
php 微信公众平台开发模式实现多客服的实例代码
2016/11/07 PHP
php正则表达式基本知识与应用详解【经典教程】
2017/04/17 PHP
PHP基于curl post实现发送url及相关中文乱码问题解决方法
2017/11/25 PHP
基于jquery的鼠标拖动效果代码
2012/05/30 Javascript
jQuery操作cookie方法实例教程
2014/11/25 Javascript
轻松实现jquery手风琴效果
2016/01/14 Javascript
JavaScript快速切换繁体中文和简体中文的方法及网站支持简繁体切换的绝招
2016/03/07 Javascript
Bootstrap每天必学之滚动监听
2016/03/16 Javascript
jQuery获取单击节点对象的方法
2016/06/02 Javascript
jQuery下拉框的简单应用
2016/06/24 Javascript
react路由配置方式详解
2017/08/07 Javascript
JavaScript中附件预览功能实现详解(推荐)
2017/08/15 Javascript
jquery之基本选择器practice(实例讲解)
2017/09/30 jQuery
解决layui页面按钮点击无反应,也不报错的问题
2019/09/29 Javascript
Python中的Matplotlib模块入门教程
2015/04/15 Python
Python使用django获取用户IP地址的方法
2015/05/11 Python
Python算法输出1-9数组形成的结果为100的所有运算式
2017/11/03 Python
简述:我为什么选择Python而不是Matlab和R语言
2017/11/14 Python
Python生成任意范围任意精度的随机数方法
2018/04/09 Python
在Pycharm中自动添加时间日期作者等信息的方法
2019/01/16 Python
Python Selenium 之关闭窗口close与quit的方法
2019/02/13 Python
django框架cookie和session用法实例详解
2019/12/10 Python
Python基于gevent实现文件字符串查找器
2020/08/11 Python
HTML5到底会有什么发展?HTML5的前景展望
2015/07/07 HTML / CSS
德国狗狗用品在线商店:Schecker
2017/03/17 全球购物
仓库门卫岗位职责
2013/12/22 职场文书
代收款委托书范本
2014/10/01 职场文书
2014年药店工作总结
2014/11/20 职场文书
责任书格式
2015/01/29 职场文书
高中军训感想
2015/08/07 职场文书
简历自我评价:教师师德表现自我评价
2019/04/24 职场文书
vue响应式原理与双向数据的深入解析
2021/06/04 Vue.js