如何给Mybatis-plus再增加点plus

来源公众号:赵侠客

一、Mybatis-plus基本功能

1.1 Mybatis-plus内置方法

Mybatis-plus给我们造了很多轮子,让我们可以开箱即用,在BaseMapper中有19种操作数据库常用的方法,如Insert()deleteById()updateById()selectById()等。

我们在开发时只需要将我们的UserMapper 继承BaseMapper就可以获取这些操作数据库的常用方法,不需要再重复写这些方法了,比较方便。

@Repository
public interface UserMapper extends BaseMapper<User> {
    
    

}

Mybatis-plus在IService给我们提供了更多更为丰富的操作数据库的方法。我们在使用时只需要将我们的UserServiceImpl 继承ServiceImpl并实现IService 接口就可轻松获取这些方法。

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


}

1.2 存在的问题

Mybatis-plus确实给我们提供了很多方法,同时也限制了我们的需求,比如我有一些很常见的需求:

  • 逻辑删除数据时,将操作人记录到数据库中。 如果你使用Mybatis-plusremoveById(1L),这个方法只能将数据库逻辑位设置成删除状态,操作人是无法记录到数据库的。

  • 每张表都有一个tenant_id,我想通过tenant_id把表中的id查出来Mybatis-plus也没有一个selectIdByTenantId()的方法。那我们只能每张表都写一个selectIdByTenantId,代码确实有点冗余了。

    所以针对以上存在的问题,我们可以  Mybatis-plus再增加点plus。

二、给BaseMapper增加几个plus

2.1 给BaseMapper增加点方法

Mybatis-plus内置的方法都是承AbstractMethod 


public class DeleteById extends AbstractMethod {
    
    

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

所以我们可以写一个DeleteAndUpdateById 类然后仿照UpdateById的写法将我们的实体中的字段更新到数据库的同时将逻辑删除位设置为删除状态。

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;
    }
}

然后我们需要将DeleteAndUpdateById方法添加到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;
    }
}

写个CustomBaseMapper,继承BaseMapper、再增加我们的deleteAndUpdateById方法

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

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

最后将UserMapper继承CustomBaseMapper这样UserMapper就有了deleteAndUpdateById方法了

@Repository
public interface UserMapper extends CustomBaseMapper<User> {
    
    

}

2.2 给ISerivce增加点方法

定义 ICustomService方法继承IService

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

然后创建CustomBaseServiceImpl实现ICustomService中的方法

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()));
    }
}      

最后将我们的UserService改成继承我们自己的ICustomServiceUserServiceImpl

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

三、测试

3.1 测试方法

通过上面的改造,我们所有的Service都有了deleteAndUpdateById()方法和selectByTenantIds()方法。

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);
    }
}

四、总结

这里我只是给Mybatis-plus增加了两个plus功能,更多的功能可以要根据自己的需求在CustomBaseMapperICustomService中添加就好了,主要可以扩展的Plus点有以下:

  • 改写Mybatis-plus内置满足不了我们实际需求的方法
  • 代码中很多通用的方法可以抽取成Plus公共功能

源码地址:https://gitee.com/whzhaochao/mybatis-plus-plus

原文地址:https://mp.weixin.qq.com/s/JnS9pmZvlvTvnutnpdYAwA

猜你喜欢

转载自blog.csdn.net/whzhaochao/article/details/132778212