How to add more plus to Mybatis-plus

Source public account: Zhao Xiake

1. Basic functions of Mybatis-plus

1.1 Mybatis-plus built-in methods

Mybatis-plusIt has built many wheels for us so that we can use them out of the box. BaseMapperThere are 19 commonly used methods for operating databases, such as Insert(), deleteById(), updateById(), selectById()etc.

When developing, we only need to inherit our UserMapper inheritance BaseMapperto obtain these common methods for operating the database. We do not need to rewrite these methods again, which is more convenient.

@Repository
public interface UserMapper extends BaseMapper<User> {
    
    

}

Mybatis-plus IServiceprovides us with more and richer methods of operating databases. UserServiceImpl When we use it, we only need to inherit ours ServiceImpland implement IService the interface to easily obtain these methods.

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IService {
    
    


}

1.2 Problems

Mybatis-plusIt does provide us with many methods, but also limits our needs. For example, I have some very common needs:

  • When logically deleting data, the operator is recorded in the database. If you use Mybatis-plusthis removeById(1L)method, this method can only set the database logical bit to the deleted state, and the operator cannot record it into the database.

  • Each table has a tenant_id. I want to find out the ID in the table through tenant_id , Mybatis-plusbut there is no selectIdByTenantId()way. Then we can only write one for each table selectIdByTenantId, and the code is indeed a bit redundant.

    So in response to the above existing problems, we can  Mybatis-plusadd a little more plus.

2. Add a few plus to BaseMapper

2.1 Add some methods to BaseMapper

Mybatis-plusThe built-in methods are inheritedAbstractMethod 


public class DeleteById extends AbstractMethod {
    
    

    public DeleteById() {
    
    
        super("deleteById");
    }
}

So we can write a DeleteAndUpdateByIdclass and then imitate UpdateByIdthe writing method to update the fields in our entity to the database and set the tombstone bit to the deleted state.

public class DeleteAndUpdateById extends AbstractMethod {
    
    


    /**
     * 注入自定义 MappedStatement
     * 根据id逻辑删除,顺带更新数据
     *
     * @param mapperClass mapper 接口
     * @param modelClass  mapper 泛型
     * @param tableInfo   数据库表反射信息
     * @return MappedStatement
     */
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
    
    
        String methodName = CustomSqlMethod.DELETE_AND_UPDATE_BY_ID.getMethod();
        String logicSql = CustomSqlMethod.DELETE_AND_UPDATE_BY_ID.getSql();
        final String additional = optlockVersion(tableInfo) + tableInfo.getLogicDeleteSql(true, true);
        logicSql = String.format(logicSql,
                tableInfo.getTableName(),
                sqlSet(false, false, tableInfo, false, ENTITY, ENTITY_DOT),
                tableInfo.getKeyColumn(),
                ENTITY_DOT + tableInfo.getKeyProperty(),
                additional);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, logicSql, modelClass);
        return addUpdateMappedStatement(mapperClass, modelClass, methodName, sqlSource);
    }

    /**
     * SQL 更新 set 语句
     *
     * @param logic          是否逻辑删除注入器
     * @param ew             是否存在 UpdateWrapper 条件
     * @param table          表信息
     * @param judgeAliasNull
     * @param alias          别名
     * @param prefix         前缀
     * @return sql
     */
    @Override
    protected String sqlSet(boolean logic, boolean ew, TableInfo table, boolean judgeAliasNull, String alias, String prefix) {
    
    
        StringBuilder sqlScriptBuilder = new StringBuilder();
        // 添加删除的sql
        sqlScriptBuilder.append(table.getLogicDeleteSql(false, false))
                .append(DOT_NEWLINE);
        // 添加更新的sql
        sqlScriptBuilder.append(table.getAllSqlSet(true, prefix));
        String sqlScript = sqlScriptBuilder.toString();
        if (judgeAliasNull) {
    
    
            sqlScript = SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", alias), true);
        }
        if (ew) {
    
    
            sqlScript += NEWLINE;
            sqlScript += convertIfEwParam(U_WRAPPER_SQL_SET, false);
        }
        sqlScript = SqlScriptUtils.convertSet(sqlScript);
        return sqlScript;
    }
}

Then we need to DeleteAndUpdateByIdadd the method to DefaultSqlInjector.

@Component
public class CustomSqlInjector extends DefaultSqlInjector {
    
    

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
    
    
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
        methodList.add(new DeleteAndUpdateById());
        return methodList;
    }
}

Write one CustomBaseMapper, inherit it BaseMapper, and add our deleteAndUpdateByIdmethods

public interface CustomBaseMapper<T> extends com.baomidou.mybatisplus.core.mapper.BaseMapper<T> {
    
    

    /**
     * 根据id做逻辑删除,并同时修改内容
     *
     * @param entity
     * @return
     */
    int deleteAndUpdateById(@Param(Constants.ENTITY) T entity);
}

Finally, it will UserMapperbe inherited CustomBaseMapperso that UserMapper has deleteAndUpdateByIda method.

@Repository
public interface UserMapper extends CustomBaseMapper<User> {
    
    

}

2.2 Add some methods to IServce

Define  ICustomServicemethod inheritanceIService

public interface ICustomService<T> extends IService<T> {
    
    
    List<Long> selectByTenantIds(List<Long> tenantIds);
    int deleteAndUpdateById(@Param(Constants.ENTITY) T entity);
}

Then create the method in CustomBaseServiceImplthe implementationICustomService

public class CustomBaseServiceImpl<M extends CustomBaseMapper<T>, T extends BaseDomain> extends ServiceImpl<M, T> {
    
    
    /**
     * 删除并更新内容 根据ID
     *
     * @param entity 对象
     * @return
     */
    public int deleteAndUpdateById(T entity) {
    
    
        return baseMapper.deleteAndUpdateById(entity);
    }


    public List<Long> selectByTenantIds(List<Long> tenantIds) {
    
    
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id");
        queryWrapper.in(!tenantIds.contains(0L), "tenant_id", tenantIds);
        return listObjs(queryWrapper, id -> Long.valueOf(id.toString()));
    }
}      

Finally, change ours UserServiceto inherit our own ICustomService,UserServiceImpl

public interface ICustomService<T> extends IService<T> {
    
    
    List<Long> selectByTenantIds(List<Long> tenantIds);
    int deleteAndUpdateById(@Param(Constants.ENTITY) T entity);
}

3. Test

3.1 Test method

Through the above transformation, all our services have deleteAndUpdateById()methods and selectByTenantIds()methods.

class ApplicationTests {
    
    

    @Resource
    private UserService userService;

    @Test
    void testDeleteAndUpadteById() {
    
    
        User user = userService.getById(1L);
        user.setModifiedBy("赵侠客");
        user.setModifiedAt(LocalDateTime.now());
        userService.deleteAndUpdateById(user);
        User dbUser = userService.getById(1L);
        Assert.isTrue(dbUser == null, "删除成功");
    }

    @Test
    void test() {
    
    
        var userIds = userService.selectByTenantIds(List.of(1L));
        log.info("userIds:{}", userIds);
        Assert.isTrue(userIds != null);
    }
}

4. Summary

Here I just Mybatis-plusadded two plus functions. More functions can be added in CustomBaseMapperand according to your own needs ICustomService. The main plus points that can be expanded are as follows:

  • Rewrite the built-in methods of Mybatis-plus that cannot meet our actual needs
  • Many common methods in the code can be extracted into Plus public functions

Source code address: https://gitee.com/whzhaochao/mybatis-plus-plus

Original address: https://mp.weixin.qq.com/s/JnS9pmZvlvTvnutnpdYAwA

Guess you like

Origin blog.csdn.net/whzhaochao/article/details/132778212