MySQL池化框架学习连接池自定义
目录
- 引言
- 可池化对象
- 池化工厂
- 对象池
- API封装
引言
最近在学习了通用池化框架commons-pool2
实践之后,再HTTP性能测试中进行了实践,结果出乎意料,对于性能提升没啥卵用。经过我自己的本地测试,性能也是足够好的。
后来我仔细想了想,原来是我用错地方了。本来想自己写一个Redis的连接池的没想到,jedis
的连接池本身就是commons-pool2
开发的,让我有点意外,看来想的是一样的。commons-pool2
用来做连接池是非常不错的。
我仔细找了找,发现还缺一个本地的MySQL连接池,而不是springboot那样需要启动一个服务才行。当然应该也是有的,不过我非常想自己写一个然后进行各类测试,所以也没有仔细找。
可池化对象
首先,我们需要一个可池化对象,这里我选用了com.funtester.db.mysql.FunMySql
,这是一个我自己写的单链接的MySQL对象。我计划用这个作为基础可池化对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | 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
的时候进行连接的回收。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /** * 池化工厂类 */ 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
对象池。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | / * * * 自定义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,暴露给用户使用,这样用户就不用关心连接的回收问题了。
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | / * * * 借出对象 * @ 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连接池自定义的资料请关注服务器之家其它相关文章!
原文链接:https://mp.weixin.qq.com/s/3VYzupjP8URkOYakidNOrg
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。