Teach you step by step how to expand (crack) the sql generation of mybatisplus | JD Cloud Technology Team

Common CRUD methods of mybatisplus

As we all know, mybatisplus provides powerful code generation capabilities. The definitions of commonly used CRUD methods (such as insert, update, delete, query, etc.) generated by it by default can help us save a lot of manual labor.

These commonly used CRUD methods are defined in it BaseMapper. When we use it, inheriting this BaseMapperclass will have these capabilities by default.

BaseMapper.png

If we need similar universal Sql in our business, how should we implement it?

Is similar Sql defined in each Mapper?

Obviously this is the stupidest method.

At this time we can use mybatisplusthis mature framework to implement the general Sql we want.

Extend common CRUD methods

Add a new general sql

For example, if there is a requirement that all tables or some tables in the project need to execute a similar query, such as `SelectByErp`, then it can be implemented like this. (This is the simplest SQL implementation. When used, more complex SQL can be implemented according to business needs: for example, a multi-tenant system automatically adds tenant id parameters, and a sub-database and sub-table system adds sub-database and sub-table field condition judgment)

  1. Define a SelectByErpclass, inherit AbstractMethodthe class, and implement injectMappedStatementthe methods

  2. Define sql method names, sql templates, and implement sql splicing and assembly

/**
 * 新增一个通用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. Define a sql injector GyhSqlInjectorand add SelectByErpobjects

// 需注入到spring容器中
@Component
public 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. Define a basic Mapper GyhBaseMapperand add selectByErpmethods

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

5. If all the tables in the application that need to use this SelectByErpmethod are inherited GyhBaseMapper, then these tables will all have selectByErpthis query method, and the SQL will be automatically generated for these tables after the program is started.

public interface XXXMapper extends GyhBaseMapper<XXXTable> 

Add a mybatisplus already has sql

1. Mybatisplus commonly used CRUD methods are as shown in the picture above. These methods are automatically generated by default, but mybatisplus actually provides more methods, as shown below. As long as we add them at startup, they can be used.

method.png

2. For example, I want to use AlwaysUpdateSomeColumnByIda method that can only update the fields I need when updating, without updating all fields. The steps to add are as follows.

3. Define a sql injector, such as GyhSqlInjectoradding AlwaysUpdateSomeColumnByIdobjects

@Component
public 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. Define a basic Mapper, such as GyhBaseMapperadding alwaysUpdateSomeColumnByIdmethods

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

5. GyhBaseMapperOther inherited Mappers will automatically have alwaysUpdateSomeColumnByIdmethods

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

6. GyhBaseMapperOther inherited Mappers will automatically have alwaysUpdateSomeColumnByIdmethods

Edit a mybatisplus existing sql

1. If you want to edit an existing sql in mybatisplus, such as a sub-database and sub-table system, updateByIdwhen performing the operation, although the primary key ID has been determined, the target table is uncertain. At this time, the sql may be executed on multiple tables, resulting in a waste of resources. , and the sub-database and sub-table fields cannot be modified. The default ones updateByIdcannot be used and need to be modified. The following takes shardingspheresub-database and sub-table as an example.

2. Define a UpdateByIdWithShardingclass and inherit UpdateByIdthe class

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. Define a sql injector GyhSqlInjectorand add UpdateByIdWithShardingobjects

// 需注入到spring容器中
@Component
public 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. Define a basic Mapper GyhBaseMapperand add new selectByIdmethods

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

5. All tables participating in table sharding are inherited when defining Mapper GyhBaseMapper. Then when using its updateByIdmethod, the judgment of sharding database and table will be automatically added, accurately hitting the target table, and reducing the waste of resources in other sharding queries.


The above are mybatisplussome simple modifications, I hope it can provide you with a little help~

Author: JD Technology Guo Yanhong

Source: JD Cloud Developer Community Please indicate the source when reprinting

Alibaba Cloud suffered a serious failure and all products were affected (restored). Tumblr cooled down the Russian operating system Aurora OS 5.0. New UI unveiled Delphi 12 & C++ Builder 12, RAD Studio 12. Many Internet companies urgently recruit Hongmeng programmers. UNIX time is about to enter the 1.7 billion era (already entered). Meituan recruits troops and plans to develop the Hongmeng system App. Amazon develops a Linux-based operating system to get rid of Android's dependence on .NET 8 on Linux. The independent size is reduced by 50%. FFmpeg 6.1 "Heaviside" is released
{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/u/4090830/blog/10141961