首页 » Web前端 » phpsql扩大技巧_手把手教你若何扩展破解mybatisplus的sql生成

phpsql扩大技巧_手把手教你若何扩展破解mybatisplus的sql生成

访客 2024-12-05 0

扫一扫用手机浏览

文章目录 [+]

他的 BaseMapper 中定义了这些常用的 CRUD 方法,我们在利用时,继续这个 BaseMapper 类就默认拥有了这些能力。

如果我们的业务中,须要类似的通用 Sql 时,该如何实现呢?

phpsql扩大技巧_手把手教你若何扩展破解mybatisplus的sql生成

是每个 Mapper 中都定义一遍类似的 Sql 吗?

phpsql扩大技巧_手把手教你若何扩展破解mybatisplus的sql生成
(图片来自网络侵删)

显然这是最笨的一种方法。

此时我们可以借助 mybatisplus 这个成熟框架,来实现我们想要的通用 Sql。

扩展常用 CRUD 方法新增一个通用 sql

比如有一个这样的需求,项目中所有表或某一些表,都要实行一个类似的查询,如 `SelectByErp`,那么可以这样实现。
(这是一个最大略的 sql 实现,利用时可以根据业务需求实现更为繁芜的 sql:比如多租户系统自动增加租户 id 参数、分库分表系统增加分库分表字段条件判断)

定义一个 SelectByErp 类,继续 AbstractMethod 类,并实现 injectMappedStatement 方法定义 sql 方法名、sql 模板、实现 sql 的拼接组装

/ 新增一个通用sql /public class SelectByErp extends AbstractMethod { // 须要查询的列名 private final String erpColumn = "erp"; // sql方法名 private final String method = "selectByErp"; // sql模板 private final String sqlTemplate = "SELECT %s FROM %s WHERE %s=#{%s} %s"; @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { // 获取须要查询的字段名及属性名 TableFieldInfo erpFiled = getErpProperty(tableInfo); // 拼接组装sql SqlSource sqlSource = new RawSqlSource(configuration, String.format(sqlTemplate, sqlSelectColumns(tableInfo, false), tableInfo.getTableName(), erpFiled.getColumn(), erpFiled.getProperty(), tableInfo.getLogicDeleteSql(true, false)), Object.class); return this.addSelectMappedStatementForTable(mapperClass, method, sqlSource, tableInfo);}/ 查询erp列信息 / private TableFieldInfo getErpProperty(TableInfo tableInfo) { List<TableFieldInfo> fieldList = tableInfo.getFieldList(); TableFieldInfo erpField = fieldList.stream().filter(filed -> filed.getColumn().equals(erpColumn)).findFirst().get(); return erpField; }

3. 定义一个 sql 注入器 GyhSqlInjector,添加 SelectByErp 工具

// 需注入到spring容器中@Componentpublic class GyhSqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass) { List<AbstractMethod> methodList = super.getMethodList(mapperClass); // 增加 SelectByErp工具,程序启动后自动加载 methodList.add(new SelectByErp()); return methodList; }}

4. 定义一个根本 MapperGyhBaseMapper,添加 selectByErp 方法

/ 自定义的通用Mapper /public interface GyhBaseMapper<T> extends BaseMapper<T> { List<T> selectByErp(String erp);}

5. 运用中须要利用该 SelectByErp 方法的表,都继续 GyhBaseMapper,那么这些表将都拥有了 selectByErp 这个查询方法,程序启动后会自动为这些表天生该 sql。

public interface XXXMapper extends GyhBaseMapper<XXXTable> 添加一个 mybatisplus 已有 sql

1.mybatisplus 常用 CRUD 方法如最上图,这些方法已经默认会自动天生,但 mybatisplus 实在供应了更多的方法,如下图,只要我们在启动时添加进去,就可以利用了。

2. 比如我想利用 AlwaysUpdateSomeColumnById 方法,该方法可以在更新时只更新我须要的字段,不进行全字段更新。
添加步骤如下。

3. 定义一个 sql 注入器 ,如 GyhSqlInjector,添加 AlwaysUpdateSomeColumnById 工具

@Componentpublic class GyhSqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass) { List<AbstractMethod> methodList = super.getMethodList(mapperClass); // 添加 AlwaysUpdateSomeColumnById 工具 methodList.add(new AlwaysUpdateSomeColumnById()); return methodList; }}

4. 定义一个根本 Mapper 如 GyhBaseMapper,添加 alwaysUpdateSomeColumnById 方法

/ 自定义的通用Mapper /public interface GyhBaseMapper<T> extends BaseMapper<T> { int alwaysUpdateSomeColumnById(@Param(Constants.ENTITY) T entity);}

5. 继续 GyhBaseMapper 的其他 Mapper,将自动拥有 alwaysUpdateSomeColumnById 方法

/ 自定义的通用Mapper /public interface GyhBaseMapper<T> extends BaseMapper<T> { int alwaysUpdateSomeColumnById(@Param(Constants.ENTITY) T entity);}

6. 继续 GyhBaseMapper 的其他 Mapper,将自动拥有 alwaysUpdateSomeColumnById 方法

编辑一个 mybatisplus 已有 sql

1. 如果想编辑一个 mybatisplus 已有 sql,比如分库分表系统,实行 updateById 操作时,虽然主键 Id 已确定,但目标表不愿定,此时可能导致该 sql 在多张表上实行,造成资源摧残浪费蹂躏,并且分库分表字段不可修正,默认的 updateById 不能用,须要改造。
以下以 shardingsphere 分库分表为例。

2. 定义一个 UpdateByIdWithSharding 类,继续 UpdateById 类

public class UpdateByIdWithSharding extends UpdateById { private String columnDot = "`"; private YamlShardingRuleConfiguration yamlShardingRuleConfiguration; // 注入shardingsphere的分库分表配置信息 public UpdateByIdWithSharding(YamlShardingRuleConfiguration yamlShardingRuleConfiguration) { this.yamlShardingRuleConfiguration = yamlShardingRuleConfiguration; } @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { String tableName = tableInfo.getTableName(); // shardingsphere 分库分表配置信息 Map<String, YamlTableRuleConfiguration> tables = yamlShardingRuleConfiguration.getTables(); // 判断当前表是否设置了分表字段 if (tables.containsKey(tableName)) { YamlTableRuleConfiguration tableRuleConfiguration = tables.get(tableName); // 获取分表字段 String shardingColumn = tableRuleConfiguration.getTableStrategy().getStandard().getShardingColumn(); // 构建sql boolean logicDelete = tableInfo.isLogicDelete(); SqlMethod sqlMethod = SqlMethod.UPDATE_BY_ID; // 增加分表字段判断 String shardingAdditional = getShardingColumnWhere(tableInfo, shardingColumn); // 是否判断逻辑删除字段 final String additional = optlockVersion() + tableInfo.getLogicDeleteSql(true, false); shardingAdditional = shardingAdditional + additional; String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), getSqlSet(logicDelete, tableInfo, shardingColumn), tableInfo.getKeyColumn(), ENTITY_DOT + tableInfo.getKeyProperty(), shardingAdditional); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); return addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource); } else { return super.injectMappedStatement(mapperClass, modelClass, tableInfo); } } / where条件增加分表字段 / private String getShardingColumnWhere(TableInfo tableInfo, String shardingColumn) { StringBuilder shardingWhere = new StringBuilder(); shardingWhere.append(" AND ").append(shardingColumn).append("=#{"); shardingWhere.append(ENTITY_DOT); TableFieldInfo fieldInfo = tableInfo.getFieldList().stream() .filter(f -> f.getColumn().replaceAll(columnDot, StringUtils.EMPTY).equals(shardingColumn)) .findFirst().get(); shardingWhere.append(fieldInfo.getEl()); shardingWhere.append("}"); return shardingWhere.toString(); } / set模块去掉分表字段 / public String getSqlSet(boolean ignoreLogicDelFiled, TableInfo tableInfo, String shardingColumn) { List<TableFieldInfo> fieldList = tableInfo.getFieldList(); // 去掉分表字段的set设置,即不修正分表字段 String rmShardingColumnSet = fieldList.stream() .filter(i -> ignoreLogicDelFiled ? !(tableInfo.isLogicDelete() && i.isLogicDelete()) : true) .filter(i -> !i.getColumn().equals(shardingColumn)) .map(i -> i.getSqlSet(ENTITY_DOT)) .filter(Objects::nonNull).collect(joining(NEWLINE)); return rmShardingColumnSet; }}

3. 定义一个 sql 注入器 GyhSqlInjector,添加 UpdateByIdWithSharding 工具

// 需注入到spring容器中@Componentpublic class GyhSqlInjector extends DefaultSqlInjector { / shardingsphere 配置信息 / @Autowired private YamlShardingRuleConfiguration yamlShardingRuleConfiguration; @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass) { List<AbstractMethod> methodList = super.getMethodList(mapperClass); // 添加 UpdateByIdWithSharding 工具,并注入分库分表信息 methodList.add(new UpdateByIdWithSharding(yamlShardingRuleConfiguration)); return methodList; }}

4. 定义一个根本 MapperGyhBaseMapper,添加新的 selectById 方法

/ 自定义的通用Mapper /public interface GyhBaseMapper<T> extends BaseMapper<T> { int updateById(@Param(Constants.ENTITY) T entity);}

5. 所有参与分表的表,在定义 Mapper 时继续 GyhBaseMapper,那么在利用他的 updateById 方法时,将自动增加分库分表判断,准确命中目标表,减少其他分表查询的资源摧残浪费蹂躏。

以上是针对 mybatisplus 的一些大略改造,希望能为你供应一点点帮助~

作者:京东科技 郭艳红

来源:京东云开拓者社区 转载请注明来源

相关文章