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部分操作
Apr 05 MySQL
详解Mysql 函数调用优化
Apr 07 MySQL
MySql学习笔记之事务隔离级别详解
May 12 MySQL
MySQL 5.7常见数据类型
Jul 15 MySQL
mysql创建存储过程及函数详解
Dec 04 MySQL
SQL注入详解及防范方法
Dec 06 MySQL
MySQL创建定时任务
Jan 22 MySQL
MYSQL如何查看进程和kill进程
Mar 13 MySQL
MySQL中优化SQL语句的方法(show status、explain分析服务器状态信息)
Apr 09 MySQL
MySQL 原理与优化之原数据锁的应用
Aug 14 MySQL
了解MySQL查询语句执行过程(5大组件)
Aug 14 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
PHP静态类
2006/11/25 PHP
php求两个目录的相对路径示例(php获取相对路径)
2014/03/27 PHP
php简单实现sql防注入的方法
2016/04/22 PHP
php 将json格式数据转换成数组的方法
2018/08/21 PHP
PHP保存Base64图片base64_decode的问题整理
2019/11/04 PHP
用javascript实现改变TEXTAREA滚动条和按钮的颜色,以及怎样让滚动条变得扁平
2007/04/20 Javascript
用js实现键盘方向键翻页功能的代码
2007/06/03 Javascript
javascript判断iphone/android手机横竖屏模式的函数
2011/12/20 Javascript
自己实现ajax封装示例分享
2014/04/01 Javascript
jQuery的:parent选择器定义和用法
2014/07/01 Javascript
js style动态设置table高度
2014/10/21 Javascript
Bootstrap基本组件学习笔记之按钮组(8)
2016/12/07 Javascript
vue-cli的webpack模板项目配置文件分析
2017/04/01 Javascript
对Vue beforeRouteEnter 的next执行时机详解
2018/08/25 Javascript
实例分析编写vue组件方法
2019/02/12 Javascript
小程序新版订阅消息模板消息
2019/12/31 Javascript
element-ui中el-upload多文件一次性上传的实现
2020/12/02 Javascript
[42:32]完美世界DOTA2联赛PWL S2 LBZS vs FTD.C 第二场 11.27
2020/12/01 DOTA
Python将多个excel表格合并为一个表格
2021/02/22 Python
python中实现将多个print输出合成一个数组
2018/04/19 Python
解决pandas中读取中文名称的csv文件报错的问题
2018/07/04 Python
python判断一个对象是否可迭代的例子
2019/07/22 Python
Python enumerate内置库用法解析
2020/02/24 Python
Keras - GPU ID 和显存占用设定步骤
2020/06/22 Python
Jupyter Notebook 远程访问配置详解
2021/01/11 Python
python利用文件时间批量重命名照片和视频
2021/02/09 Python
html5触摸事件判断滑动方向的实现
2018/06/05 HTML / CSS
斯洛伐克香水和化妆品购物网站:Parfemy-Elnino.sk
2020/01/28 全球购物
办公室主任先进事迹
2014/01/18 职场文书
求职信的最佳写作思路
2014/02/01 职场文书
教师工作总结范文2014
2014/11/10 职场文书
2019学生会干事辞职信
2019/06/27 职场文书
vue-element-admin项目导入和导出的实现
2021/05/21 Vue.js
Anaconda配置各版本Pytorch的实现
2021/08/07 Python
SpringBoot2零基础到精通之数据与页面响应
2022/03/22 Java/Android
20180830晚上第一届KSL半决赛 雨神vs解冻(二龙 三炮解说)
2022/04/01 星际争霸