Mybatis Plus custom IService and BaseMapper

Mybatis Plus custom IService and BaseMapper

1, Why did you study this thing

Recently, I was independently responsible for the service R & D of a java module of innovative business in the company. When building the project, I chose Mybatis Plus to do the work of database Dao layer. Although it's not the first time I've contacted Mybatis Plus since I started working, the previous contacts were directly used after the predecessors in the group built the framework. This time, I completely took the knife and went to battle myself. To customize IService and BaseMapper by yourself actually comes from a problem: when a field of an entity class is identified by @ tablelogic (logical deletion), the boolean updateById(T entity) method provided in IService can no longer edit the modified annotation field. hhh, for this reason, all business logic deleted interfaces of blind write are not effective. "You may say that you can directly use the remove * * series interfaces provided in IService, but these interfaces cannot update the [current operator name, operator ID, operation time...] and other information in the business at the same time when they are logically deleted." in short, because of laziness, you don't want to customize SQL in the corresponding mapper for each database model, On the other hand, if you need to make corresponding adjustments to adjust the database fields, as a technical dog, you don't think it's cool to adjust one by one.

2, Implementation steps

2.1 customize an injected method class

Create a new class MyUpdateById.class, and inherit the abstract class AbstractMethod.class under the package com.baidu.mybatisplus.core.injector.

public class MyUpdateById extends AbstractMethod {

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        SqlMethod sqlMethod = SqlMethod.UPDATE_BY_ID;
        //The method name needs to be consistent with the name in mapper
        String method = "updateByIdWithLogicDelete";
        final String additional = optlockVersion() + tableInfo.getLogicDeleteSql(true, true);
        //Because the transformation is based on updateById(T entity), here we only change the logic in sqlSet to false without adjusting other parameters
        String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(),
                sqlSet(false, false, tableInfo, false, ENTITY, ENTITY_DOT),
                tableInfo.getKeyColumn(), ENTITY_DOT + tableInfo.getKeyProperty(), additional);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return addUpdateMappedStatement(mapperClass, modelClass, method, sqlSource);
    }
}

Some additional instructions. In fact, when you open AbstractMethod with IDEA, you will find that the implementation classes of the abstract class are the methods provided in BaseMapper. As shown below:

When I was looking for the reason why updateById(T entity) automatically removed the @ LogicDelete annotation field in the set statement part, I found the implementation class DeleteById.class of AbstractMethod. Habitually, after setting a breakpoint for the injectMappedStatement method of DeleteById.class, I started the service. I will see that each entity will execute this method first, Initialize the execution SQL template of the entity, as shown in the following figure:

The data of the sql variable is as follows (the name of the worksheet and some other information are hidden):

<script>
UPDATE table_activity <set>
<if test="et['code'] != null">code=#{et.code},</if>
<if test="et['name'] != null">name=#{et.name},</if>
<if test="et['scopeType'] != null">scope_type=#{et.scopeType},</if>
<if test="et['scopeCode'] != null">scope_code=#{et.scopeCode},</if>
<if test="et['itemCode'] != null">item_code=#{et.itemCode},</if>
<if test="et['sector'] != null">sector=#{et.sector},</if>
<if test="et['helpFileUrls'] != null">help_file_urls=#{et.helpFileUrls},</if>
<if test="et['status'] != null">status=#{et.status},</if>
<if test="et['comment'] != null">comment=#{et.comment},</if>
<if test="et['updater'] != null">updater=#{et.updater},</if>
<if test="et['updateBy'] != null">update_by=#{et.updateBy},</if>
<if test="et['createdAt'] != null">create_at=#{et.createdAt},</if>
<if test="et['updatedAt'] != null">update_at=#{et.updatedAt},</if>
</set> WHERE id=#{et.id} <if test="et instanceof java.util.Map"> AND ${et.MP_OPTLOCK_VERSION_COLUMN}=#{et.MP_OPTLOCK_VERSION_ORIGINAL}</if> AND is_delete=0
</script>

After the customized MyUpdateById is configured successfully, we will get the set part of the isDelete field, which is very similar to the updateById. For details, please refer to the following information

2.2 customize an SQL injector

Define a MySQL injector.class, inherit the DefaultSqlInjector.class under the com.baomidou.mybatisplus.core.injector package, rewrite the interface for obtaining the method list, and add the method configured in the first step to the interface.

public class MySqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {

        //Get the getMethodList method of the parent class
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);

        //Customize updates with logical deletion
        methodList.add(new MyUpdateById());


        return methodList;
    }
}

2.3 add a custom SQL injector to the configuration

@Bean
    public MySqlInjector myLogicSqlInjector() {
        return new MySqlInjector();
    }

2.4 customize a general BaseMapper interface and add the updateByIdWithLogicDelete(@Param(Constants.ENTITY)T entity) method

public interface MyBaseMapper<T> extends BaseMapper<T> {

    int updateByIdWithLogicDelete(@Param(Constants.ENTITY) T entity);

}

In fact, up to now, we can use the functions of the mapper module independently

The updateByIdWithLogicDelete method defined by us can be called directly through the injected baseMapper.

But in fact, to do so, we still need to define a method in each service and call the method through mapper. Since it is such a general method, maybe 70% of the business models will involve updating and saving some business information during logical deletion, we can simply use our own IMyService instead of MyBatis Plus to provide IService to us, On the basis of including IService, expand the common write method in your project, can't you simply implement it ~

2.5 define a custom IMyService interface and provide some custom general methods

public interface IMyBaseService<T> extends IService<T> {

    /**
     * The upgrade of updateById includes the update of logically deleted fields
     * @param entity
     * @return
     */
    boolean updateByIdWithLogicDelete(T entity);
}

2.6 add the implementation of IMyService

@SuppressWarnings("unchecked")
public class MyBaseServiceImpl <M extends MyBaseMapper<T>, T> extends ServiceImpl<M, T> implements IMyBaseService<T>{

    @Override
    public boolean updateByIdWithLogicDelete(T entity) {
        return retBool(baseMapper.updateByIdWithLogicDelete(entity));
    }
}

2.7 what's left is to use it!

1. Relay IMyService on service

public interface IDictService extends IMyBaseService<Dict>

2. Relay the implementation of IMyBaseService in the implementation of service

@Service
public class DictServiceImpl extends MyBaseServiceImpl<DictMapper, Dict> implements IDictService {...}

3. Inherit MyBaseMapper in mapper instead of IBaseMapper

public interface DictMapper extends MyBaseMapper<Dict> {
}

summary

My recent work is so boring and powerless. When can I have a standardized R & D process. When you are too fast, everything that has been reviewed has passed everyone's review. After you have developed the interface, you will receive changes in product requirements, changes in the process of connecting another service on the leadership side... And deal with fuzzy and borderless data. Recent work is very annoying. It's not easy to work. It's really difficult to get online for this project. No colleagues have worked overtime with me

Keywords: Java MySQL

Added by firepages on Wed, 01 Dec 2021 14:45:19 +0200