日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

SpringBoot使用 druid 連接池來優化分頁語句

瀏覽:25日期:2023-04-11 13:08:36

一、前言

一個老系統隨著數據量越來越大,我們察覺到部分分頁語句拖慢了我們的速度。

鑒于老系統的使用方式,不打算使用pagehelper和mybatis-plus來處理,加上系統里使用得是druid連接池,考慮直接使用druid來優化。

二、老代碼

老代碼是使用得一個mybatis插件進行的分頁,分頁的核心代碼如下:

// 記錄統計的 sqlString countSql = 'select count(0) from (' + sql+ ') tmp_count';PreparedStatement countStmt = connection.prepareStatement(countSql);BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql, boundSql.getParameterMappings(), parameterObject);setParameters(countStmt, mappedStatement, countBS,parameterObject);

在原始的 sql 外面包裝了一個 count sql,當然很多插件都是這樣做的。

三、druid 的 PagerUtil

示例 sql(有比較復雜的坐標計算)

SELECT g.* , ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN((? * PI() / 180 - t.latitude * PI() / 180) / 2), 2) + COS(? * PI() / 180) * COS(t.latitude * PI() / 180) * POW(SIN((? * PI() / 180 - t.longitude * PI() / 180) / 2), 2))), 2) AS distancecd , t.agentname, t.agentlogo, t.compaddressFROM t_bas_integral_goods g LEFT JOIN t_bas_agent t ON g.agentid = t.AGENTIDWHERE t.AGENTTYPE = ’2’ AND t.pass = ’0’ AND t.dl_type = ’4’ AND g.type = 0ORDER BY distancecd ASC

使用 Druid 生成 count sql:

String countSql = PagerUtils.count(sql, DbType.mysql);System.out.println(countSql);

輸出:

SELECT COUNT(*)FROM t_bas_integral_goods g LEFT JOIN t_bas_agent t ON g.agentid = t.AGENTIDWHERE t.AGENTTYPE = ’2’ AND t.pass = ’0’ AND t.dl_type = ’4’ AND g.type = 0

我們可以看到優化后的 count sql 變得十分簡潔,坐標計算的都已經丟棄掉。 注意:PagerUtil還有limit方法用來生成limit語句,感興趣的同學可以自行試驗。

四、改造mybatis分頁插件

4.1 踩坑之路

看到上面 druid PagerUtils count 的優化效果,立馬開始改造起來,起初只改掉了countSql,

String countSql = PagerUtils.count(sql, dbType);PreparedStatement countStmt = connection.prepareStatement(countSql);BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql, boundSql.getParameterMappings(), parameterObject);setParameters(countStmt, mappedStatement, countBS,parameterObject);

啟動起來測試一番就發現報錯了,因為原始 sql 中含有?變量,優化后的 sql 已經沒有變量了,插件還會繼續給他設置變量。 我們要怎么解決這個問題呢?

我們再回頭看看pagehelper和mybatis-plus是怎么實現的!它倆都是基于jsqlparser對 sql 進行解析,然后處理。

要多加一個jsqlparser?沒必要沒必要,druid 的 sql 解析功能也是很強大的,我看了看PagerUtils.count方法的源碼,大不了用 druid 的 sql 解析實現一遍。

看了看源碼之后我陷入了沉思,有必要搞這么復雜么?有沒有更好的方法?我反復 debug 發現了,DynamicSqlSource中有帶#{xxx}這樣的原始 sql,

那么我是否可以使用 druid 先對這種 mybatis 占位符的 sql 進行優化呢?我們來試試:

示例 sql:

select * from xxx where type = #{type} order by xx

輸出:

SELECT COUNT(*)FROM xxxWHERE type = #{type}

完美?。?! 4.2 繼續踩坑

然而直接在 Mapper 上注解的 sql 還是有問題,拿不到原始的 sql,debug 發現 RawSqlSource 在構造器里就將 sql 處理成了?號掛參的形式。

@Select('select * from xxx where type = #{type} order by xx')Object test(@Param('type') String type);

那么我只能看看能不能擴展它,我找到了它是在XMLLanguageDriver里進行初始化,這下好辦了,因為我之前擴展過XMLLanguageDriver,它是可以自定義配置的。 于是我重寫了RawSqlSource, 添加上了包含 mybatis 參數占位符(#{})的rawSql字段。

/** * 原始 sql,用于方便 druid 工具進行分頁 * * @author L.cm */public class MicaRawSqlSource implements SqlSource { private final String rawSql; private final SqlSource sqlSource; public MicaRawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) { this(configuration, getSql(configuration, rootSqlNode), parameterType); } public MicaRawSqlSource(Configuration configuration, String sql, Class<?> parameterType) { SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration); Class<?> clazz = parameterType == null ? Object.class : parameterType; this.rawSql = sql; this.sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<>()); } // ... ...}

自此全部邏輯已經走通,我們再來看看我們的PagePlugin核心代碼:

// 進行分頁Configuration configuration = mappedStatement.getConfiguration();SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);Class<?> parameterType = parameterObject.getClass();Connection connection = (Connection) invocation.getArgs()[0];// 1. 對 sql 進行判斷,如果沒有 ? 號,則直接處理String boundRawSql = boundSql.getSql();if (boundRawSql.indexOf(CharPool.QUESTION_MARK) == -1) { // 不包含 ? 號 String countSql = PagerUtils.count(boundRawSql, dbType); SqlSource newSqlSource = sqlSourceParser.parse(countSql, parameterType, new HashMap<>()); BoundSql newBoundSql = newSqlSource.getBoundSql(parameterObject); int count = getCount(connection, mappedStatement, parameterObject, newBoundSql); StringBuilder sqlBuilder = new StringBuilder(boundRawSql); Page page = getPageParam(parameterObject, sqlBuilder, count); String pageSql = generatePageSql(sqlBuilder.toString(), dbType, page); // 將分頁sql語句反射回BoundSql. setField(boundSql, 'sql', pageSql); return invocation.proceed();}// 2. 按 SqlSource 進行解析SqlSource sqlSource = mappedStatement.getSqlSource();// xml 中的動態 sqlint count;if (sqlSource instanceof DynamicSqlSource) { SqlNode rootSqlNode = PagePlugin.getField(sqlSource, 'rootSqlNode'); DynamicContext context = new DynamicContext(configuration, parameterObject); rootSqlNode.apply(context); // 生成 count sql,帶 #{xxx} 變量的 sql String countSql = PagerUtils.count(context.getSql(), dbType); SqlSource newSqlSource = sqlSourceParser.parse(countSql, parameterType, context.getBindings()); BoundSql newBoundSql = newSqlSource.getBoundSql(parameterObject); count = getCount(connection, mappedStatement, parameterObject, newBoundSql);} else if (sqlSource instanceof MicaRawSqlSource) { String rawSql = ((MicaRawSqlSource) sqlSource).getRawSql(); DynamicContext context = new DynamicContext(configuration, parameterObject); // 生成 count sql,帶 #{xxx} 變量的 sql String countSql = PagerUtils.count(rawSql, dbType); SqlSource newSqlSource = sqlSourceParser.parse(countSql, parameterType, context.getBindings()); BoundSql newBoundSql = newSqlSource.getBoundSql(parameterObject); count = getCount(connection, mappedStatement, parameterObject, newBoundSql);} else { throw new IllegalArgumentException('不支持的 sql 分頁形式,請使用 xml 或者注解');}

五、結論

整個老服務通過切換到 mica(深度定制)的微服務架構(演示環境僅僅在單服務低內存配置)之后速度提升效果明顯,當然后面我們還會繼續進行優化。

到此這篇關于SpringBoot使用 druid 連接池來優化分頁語句的文章就介紹到這了,更多相關SpringBoot druid 連接池分頁內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
激情综合网五月| 美女视频黄免费的久久| 免费在线观看精品| 麻豆亚洲精品| 久久亚洲国产精品一区二区| 欧美国产极品| 国产毛片精品久久| 国产一区二区色噜噜| 日韩成人精品一区二区| 日韩在线免费| 在线一区视频| 国产欧美久久一区二区三区| 91精品福利观看| 高清一区二区| 国产videos久久| 国产成人精品亚洲日本在线观看| 欧美精品资源| 日韩视频一区| 日韩成人一级| 美女久久99| 四虎8848精品成人免费网站| 日韩中文在线电影| 久久亚洲一区| 日本亚州欧洲精品不卡| 久久久精品区| 美女av在线免费看| 日韩激情网站| 色婷婷狠狠五月综合天色拍| 日韩在线看片| 久久国产精品久久久久久电车| 玖玖玖国产精品| 久久精品99国产精品| 亚洲高清成人| 麻豆91在线播放| 日韩在线高清| 欧美精品一卡| 黑人精品一区| 中国女人久久久| 欧美亚洲一区二区三区| 色偷偷色偷偷色偷偷在线视频| 美女网站一区| 日韩精品乱码av一区二区| 精品精品久久| 日韩高清电影免费| 精品国产乱码久久久| 91精品91| 久久91视频| 久久大逼视频| 精品国产乱码久久久久久樱花| 欧美日韩色图| 亚洲精品少妇| 亚洲国产福利| 中文字幕一区二区av| 亚洲一级黄色| 欧美亚洲网站| 欧洲毛片在线视频免费观看| 奇米狠狠一区二区三区| 久久精品免费一区二区三区| 国产一区二区亚洲| 亚洲欧美日韩国产综合精品二区 | 亚洲四虎影院| 欧美有码在线| jizzjizz中国精品麻豆| 青草综合视频| 亚洲国产不卡| 国产激情在线播放| 欧美午夜网站| 久久精品国产68国产精品亚洲| 国产精品九九| 国产欧美日韩亚洲一区二区三区| 日韩精品欧美激情一区二区| 日韩精品1区2区3区| 99久久久久久中文字幕一区| 国产美女视频一区二区| 免费在线欧美视频| 群体交乱之放荡娇妻一区二区| 欧美黄页在线免费观看| 欧美午夜不卡| 国产日韩电影| 久久久久久久欧美精品| 国产欧美日韩一区二区三区四区| 在线综合视频| 免费观看不卡av| 91精品xxx在线观看| 麻豆视频观看网址久久| 日本亚洲视频在线| 亚洲精品成人一区| 亚洲精品电影| 黄色免费成人| 国产一在线精品一区在线观看| 国产精品草草| 日韩国产欧美在线视频| 模特精品在线| 蜜臀av亚洲一区中文字幕| 欧美精选一区二区三区| 国产高清不卡| 欧美成人a交片免费看| 九九九精品视频| 久久精品国产在热久久| 国产毛片精品久久| 国产精品一区二区中文字幕| 日本欧美久久久久免费播放网| 中文字幕一区二区三区四区久久| 亚洲精品国产偷自在线观看| 欧美日韩日本国产亚洲在线| 亚洲精品a级片| 欧美日韩精品一本二本三本| 欧美/亚洲一区| 欧美特黄一区| 美女久久一区| 久久aⅴ国产紧身牛仔裤| 久久xxxx精品视频| 日本亚洲欧洲无免费码在线| 青青草国产精品亚洲专区无| 国产美女撒尿一区二区| 精品午夜久久| 欧美羞羞视频| 欧美99久久| 性欧美长视频| 日韩高清在线观看一区二区| 国产视频一区二| 成人在线免费观看网站| 日韩在线高清| 五月婷婷六月综合| 综合亚洲色图| 日本亚州欧洲精品不卡| 国产麻豆精品| 亚洲综合电影| 精品欧美久久| 亚洲a成人v| 国产精品一区高清| 天堂中文av在线资源库| 亚洲精品一区二区妖精| 蜜臀久久久久久久| 国产精品亚洲产品| 国产激情在线播放| 一本一本久久| 国产美女久久| 欧美va天堂在线| 日韩av中文字幕一区二区三区| 国产亚洲高清在线观看| 麻豆网站免费在线观看| 麻豆9191精品国产| 国产精品777777在线播放 | 韩国精品主播一区二区在线观看 | 国产精品久久久久久久久免费高清| 极品av在线| 天堂av在线一区| 国产成人在线中文字幕| 蜜桃视频欧美| 国产精品videosex极品| 欧美成人久久| 麻豆国产精品一区二区三区| 群体交乱之放荡娇妻一区二区| 日本中文字幕视频一区| 日韩一区电影| 欧美在线观看天堂一区二区三区| 婷婷激情久久| 精品一区二区三区在线观看视频| 欧美日韩国产一区精品一区| 国产精品午夜av| 欧美日韩国产欧| 日韩精品三区四区| 成人午夜毛片| 亚州精品视频| 国产精品videossex久久发布| 狠狠久久婷婷| 欧美激情一区| 成人羞羞视频播放网站| 手机精品视频在线观看| 国产精品17p| 国内精品福利| 日欧美一区二区| 国产精品88久久久久久| 日韩高清一区在线| 中文字幕系列一区| 日本麻豆一区二区三区视频| 99国产精品| 黄色在线网站噜噜噜| 亚洲一二三区视频| 国产999精品在线观看| 国产成人精品一区二区免费看京| 五月激激激综合网色播 | 四虎在线精品| 99久久99久久精品国产片果冰| 亚洲欧美日本国产| 免费一级欧美在线观看视频| 在线亚洲国产精品网站| 成人亚洲一区二区| 91嫩草精品| 日本不卡不码高清免费观看| 久久久精品网| 国产精品第一国产精品| 久久要要av| 久久不卡国产精品一区二区| 亚洲一级网站| 国产一区二区三区四区| 国产精品呻吟| 色老板在线视频一区二区| 成人在线观看免费视频|