All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sicheng.common.persistence.dialect.Dialect Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
/**
 * 本作品使用 木兰公共许可证,第2版(Mulan PubL v2) 开源协议,请遵守相关条款,或者联系sicheng.net获取商用授权。
 * Copyright (c) 2016 SiCheng.Net
 * This software is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.sicheng.common.persistence.dialect;

import com.sicheng.common.config.Global;
import com.sicheng.common.persistence.interceptor.SQLHelper;

/**
 * 各个数据库的分页SQL方言
 * 类似hibernate的Dialect,但只精简出分页部分
 */
public interface Dialect {

    /**
     * 数据库本身是否支持分页当前的分页查询方式
     * 如果数据库不支持的话,则不进行数据库分页
     *
     * @return true:支持当前的分页查询方式
     */
    boolean supportsLimit();

    /**
     * 将一条普通的业务sql转换为支持分页SQL
     * 这是最常规的分页SQL
     * 单表、多对一、一对一,都使用本分页SQL,使用频率高达90%
     *
     * 
     * 如mysql
     * dialect.pagedSql("select * from user", 12, ":offset",0,":limit") 将返回
     * select * from user limit :offset,:limit
     * 
* * @param sql 业务sql * @param offset 开始条数 * @param limit 每页显示多少纪录条数 * @return 支持分页查询的sql */ String pagedSql(String sql, int offset, int limit); /** * 将一条普通的业务sql转换为 求count的SQL * 这是最常规的求count的SQL,与pagedSql()返回的SQL配合使用。 *

* 为什么default修饰的?因为本方法是后期加的。由于情况并不多样,不需要每个子类做出不同的实现,就写在了接口中。 * * @param sql 业务sql * @return 求count的SQL */ default String countSql(final String sql) { String dbType$ = Global.getConfig("jdbc.type"); final String countSql; if ("oracle".equals(dbType$)) { countSql = "select count(1) from (" + sql + ") tmp_count"; } else { //求总数时使用removeOrders()去掉 order by排序子句,一是求总数时不需要排序,二是不花费排序的性能。 //mysql5.6的子查询性能已得到极大的提升,建议使用子查询。以下语句改为子查询 //countSql = "select count(1) " + removeSelect(removeOrders(sql)); countSql = "select count(1) from (" + SQLHelper.removeOrders(sql) + ") tmp_count"; } return countSql; } /** * 将一条普通的业务sql转换为支持“二次偏移量算法”分页SQL *

* 一对多join时,使用本分页SQL,使用频率低达10% * 一对多的多表join的SQL,执行后导致左表记录数变多、分页不准、合并后不足一页的问题 * 将通过用本方法计算出来的二次偏移量来解决。 *

* “分页二次偏移量算法”暗示语法 * 只在要SQL字符串任意位置包含以下语法,就会开启“分页二次偏移量算法” * 格式:\/*paged_offset&pk=id,aid*\/ * 格式说明:字母不区分大小写。 * 格式说明:paged_offset是名称,表示使用“分页二次偏移量算法”来计算分页。 * 格式说明:pk=id,aid是告诉框架主建列是id,aid,框架使用知主键列的名称。 * 格式说明:&是两个参数之间的分隔符号 * 格式说明:放置位置,暗示语法可放在SQL的任意位置 * 示例:SELECT * \/*paged_offset&pk=id,aid*\/ FROM table_name; * * @param sql SQL语句 * @param hint 暗示语法 \/*paged_offset#pk=a.id*\/ * @param offset 开始条数(原始值) * @param limit 每页显示多少纪录条数(原始值) * @return 支持“二次偏移量算法”分页SQL */ // String pagedSql4joinOffset(String sql, String hint, int offset, int limit); /** * 将一条普通的业务sql转换为支持“二次偏移量算法”的求count的SQL(第一类) * 这是特殊的求count的SQL,与pagedSql4joinOffset()返回的SQL配合使用。 *

* 为什么default修饰的?因为本方法是后期加的。由于情况并不多样,不需要每个子类做出不同的实现,就写在了接口中。 * * @param sql SQL语句 * @param hint 暗示语法 \/*paged_offset#pk=a.id*\/ * @return 支持“二次偏移量算法”的求count的SQL */ default String countSql4joinOffset(String sql, String hint) { //////////////////////////////////////////////////////// //“二次偏移量算法”一共由3条(2类)SQL计算出偏移量,这是第一类 //////////////////////////////////////////////////////// // #求合并后的总记录数 // SELECT COUNT(t.栏目ID) AS '总记录数' FROM ( // SELECT a.id "栏目ID",COUNT(a.id) AS "合并的数量" FROM `cms_category` a LEFT JOIN cms_article b ON a.id=b.`category_id` GROUP BY a.id // ) t //取出主键从“paged_offset#pk=a.id”中取出a.id主键列名, a是表的别名 String[] arr = hint.split("#");//“paged_offset#pk=a.id”中取出pk=a.id String pk = arr[1].split("=")[1];//pk=a.id中取出a.id // 原始SQL去掉 select 子句,去掉Order by子句. // 求总数时使用removeOrders()去掉 order by排序子句,一是求总数时不需要排序,二是不花费排序的性能。 String sqlSub = SQLHelper.removeSelect(SQLHelper.removeOrders(sql)); //组装 StringBuilder sbl = new StringBuilder(); sbl.append("SELECT COUNT(idd) AS ccount FROM ( ");//ccount是别名 sbl.append("SELECT ").append(pk).append(" AS idd ").append(sqlSub); sbl.append(" GROUP BY ").append(pk);//按ID分组是核心逻辑 sbl.append(") t"); return SQLHelper.removeBreakingWhitespace(sbl.toString());//美化sql } /** * 将一条普通的业务sql转换为支持“二次偏移量算法”的求count的SQL(第二类) * 这是特殊的求count的SQL,与pagedSql4joinOffset()返回的SQL配合使用。 *

* 为什么default修饰的?因为本方法是后期加的。由于情况并不多样,不需要每个子类做出不同的实现,就写在了接口中。 * * @param sql SQL语句 * @param hint 暗示语法 \/*paged_offset#pk=a.id*\/ * @param offset 开始条数(原始值) * @param limit 每页显示多少纪录条数(原始值) * @return 支持“二次偏移量算法”的求count的SQL */ default String countSql4joinOffset(String sql, String hint, int offset, int limit) { //////////////////////////////////////////////////////// //“二次偏移量算法”一共由3条(2类)SQL计算出偏移量,这是第二类 //////////////////////////////////////////////////////// // #求未合并的2次偏移量-start // SELECT SUM(t.合并的数量) AS '2次偏移量-start' FROM ( // SELECT a.id ,COUNT(a.id) AS "合并的数量" FROM `cms_category` a LEFT JOIN cms_article b ON a.id=b.`category_id` GROUP BY a.id ORDER BY a.id LIMIT 0,10 // ) t // // #求未合并的2次偏移量-end // SELECT SUM(t.合并的数量) AS '2次偏移量-ent' FROM ( // SELECT a.id ,COUNT(a.id) AS "合并的数量" FROM `cms_category` a LEFT JOIN cms_article b ON a.id=b.`category_id` GROUP BY a.id ORDER BY a.id LIMIT 10,3 // ) t //取出主键从“paged_offset#pk=a.id”中取出a.id主键列名, a是表的别名 String[] arr = hint.split("#");//“paged_offset#pk=a.id”中取出pk=a.id String pk = arr[1].split("=")[1];//pk=a.id中取出a.id //取得sql中的原始的order By子句 String orderBy=SQLHelper.getOrders(sql); // 原始SQL去掉 select 子句,去掉Order by子句 // order by排序子句 必须放在 group by 子句的后面,SQL语法才是正确的 String sqlSub = SQLHelper.removeSelect(SQLHelper.removeOrders(sql)); //组装 StringBuilder sbl = new StringBuilder(); sbl.append("SELECT SUM(size) AS ccount FROM ( ");//ccount是别名 sbl.append("SELECT COUNT(").append(pk).append(") as size ").append(sqlSub); sbl.append(" GROUP BY ").append(pk);//按ID分组是核心逻辑 sbl.append(" "); sbl.append(orderBy); //拼上原始的order by子句,它必需要放在GROUP BY子句的后面,才是正确的语法。 sbl.append(" LIMIT ").append(offset).append(",").append(limit); sbl.append(") t"); return SQLHelper.removeBreakingWhitespace(sbl.toString());//美化sql } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy