package cn.iocoder.yudao.framework.mybatis.core.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.func.Func1; import cn.hutool.core.lang.func.LambdaUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.SortingField; import cn.iocoder.yudao.framework.mybatis.core.enums.DbTypeEnum; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * MyBatis 工具类 */ public class MyBatisUtils { private static final String MYSQL_ESCAPE_CHARACTER = "`"; public static Page buildPage(PageParam pageParam) { return buildPage(pageParam, null); } public static Page buildPage(PageParam pageParam, Collection sortingFields) { // 页码 + 数量 Page page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize()); page.setOptimizeJoinOfCountSql(false); // 关联 issue:https://gitee.com/zhijiantianya/yudao-cloud/issues/ID2QLL // 排序字段 if (CollUtil.isNotEmpty(sortingFields)) { for (SortingField sortingField : sortingFields) { page.addOrder(new OrderItem().setAsc(SortingField.ORDER_ASC.equals(sortingField.getOrder())) .setColumn(StrUtil.toUnderlineCase(sortingField.getField()))); } } return page; } @SuppressWarnings("PatternVariableCanBeUsed") public static void addOrder(Wrapper wrapper, Collection sortingFields) { if (CollUtil.isEmpty(sortingFields)) { return; } if (wrapper instanceof QueryWrapper) { QueryWrapper query = (QueryWrapper) wrapper; for (SortingField sortingField : sortingFields) { query.orderBy(true, SortingField.ORDER_ASC.equals(sortingField.getOrder()), StrUtil.toUnderlineCase(sortingField.getField())); } } else if (wrapper instanceof LambdaQueryWrapper) { // LambdaQueryWrapper 不直接支持字符串字段排序,使用 last 方法拼接 ORDER BY LambdaQueryWrapper lambdaQuery = (LambdaQueryWrapper) wrapper; StringBuilder orderBy = new StringBuilder(); for (SortingField sortingField : sortingFields) { if (StrUtil.isNotEmpty(orderBy)) { orderBy.append(", "); } orderBy.append(StrUtil.toUnderlineCase(sortingField.getField())) .append(" ") .append(SortingField.ORDER_ASC.equals(sortingField.getOrder()) ? "ASC" : "DESC"); } lambdaQuery.last("ORDER BY " + orderBy); // 另外个思路:https://blog.csdn.net/m0_59084856/article/details/138450913 } else { throw new IllegalArgumentException("Unsupported wrapper type: " + wrapper.getClass().getName()); } } /** * 将拦截器添加到链中 * 由于 MybatisPlusInterceptor 不支持添加拦截器,所以只能全量设置 * * @param interceptor 链 * @param inner 拦截器 * @param index 位置 */ public static void addInterceptor(MybatisPlusInterceptor interceptor, InnerInterceptor inner, int index) { List inners = new ArrayList<>(interceptor.getInterceptors()); inners.add(index, inner); interceptor.setInterceptors(inners); } /** * 获得 Table 对应的表名 *

* 兼容 MySQL 转义表名 `t_xxx` * * @param table 表 * @return 去除转移字符后的表名 */ public static String getTableName(Table table) { String tableName = table.getName(); if (tableName.startsWith(MYSQL_ESCAPE_CHARACTER) && tableName.endsWith(MYSQL_ESCAPE_CHARACTER)) { tableName = tableName.substring(1, tableName.length() - 1); } return tableName; } /** * 构建 Column 对象 * * @param tableName 表名 * @param tableAlias 别名 * @param column 字段名 * @return Column 对象 */ public static Column buildColumn(String tableName, Alias tableAlias, String column) { if (tableAlias != null) { tableName = tableAlias.getName(); } return new Column(tableName + StringPool.DOT + column); } /** * 跨数据库的 find_in_set 实现 * * @param column 字段名称 * @param value 查询值(不带单引号) * @return sql */ public static String findInSet(String column, Object value) { DbType dbType = JdbcUtils.getDbType(); return DbTypeEnum.getFindInSetTemplate(dbType) .replace("#{column}", column) .replace("#{value}", StrUtil.toString(value)); } /** * 将驼峰命名转换为下划线命名 * * 使用场景: * 1. fix:修复"商品统计聚合函数的别名与排序字段不符"导致的 SQL 异常 * * @param func 字段名函数(驼峰命名) * @return 字段名(下划线命名) */ public static String toUnderlineCase(Func1 func) { String fieldName = LambdaUtil.getFieldName(func); return StrUtil.toUnderlineCase(fieldName); } }