如何给Mybatis-plus再增加点plus

news2024/10/9 16:27:52

来源公众号:赵侠客

一、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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/994057.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring系列文章:Spring事务

一、事务简述 1、什么是事务&#xff08; Transaction&#xff08;tx&#xff09;&#xff09; 在⼀个业务流程当中&#xff0c;通常需要多条DML&#xff08;insert delete update&#xff09;语句共同联合才能完成&#xff0c;这 多条DML语句必须同时成功&#xff0c;或者同…

WSL 在windows 家庭版上面的安装方式

目录 1、前言 2、约束 3、安装 1、安装Hyper 2、Hyper-V启用 3、安装Linux 4、0x800701bc问题处理 结论 1、前言 适用于Windows的Linux子系统 Windows Subsystem for Linux&#xff08;简称WSL&#xff09;是一个在Windows 10\11上能够运行原生Linux二进制可执行文件&am…

一条爬虫抓取一个小网站所有数据

一条爬虫抓取一个小网站所有数据 ​ 今天闲来无事&#xff0c;写一个爬虫来玩玩。在网上冲浪的时候发现了一个搞笑的段子网&#xff0c;发现里面的内容还是比较有意思的&#xff0c;于是心血来潮&#xff0c;就想着能不能写一个Python程序&#xff0c;抓取几条数据下来看看&am…

9.3.4(数据链路层)

一. 以太网帧格式: 二.IP地址和Mac地址在网络传输中的区别: 1.源IP:数据发送方的地址. 目的IP:数据接收发的地址. 2.源Mac:相邻两个路由器传输数据时发送方的地址. 目的Mac: 相邻两个路由器传输数据时接收方的地址. 3. 在一次数据传输中,源IP和目的IP不变,源Mac和目的Mac不…

Databend 数据集成方案 | Data Infra 第 15 期

本期的 Data Infra 直播活动我们邀请到了 Databend Cloud 研发工程师-韩山杰&#xff0c;与大家分享主题为《 Databend 数据集成方案》的相关知识。 在本次分享中&#xff0c;你将会学到在云上基于 Databend 及 Databend Cloud 构建应用&#xff0c;掌握 Databend CDC 和 Data…

Validate表单组件的封装

之前一直是直接去使用别人现成的组件库&#xff0c;也没有具体去了解人家的组件是怎么封装的&#xff0c;造轮子才会更好地提高自己&#xff0c;所以尝试开始从封装Form表单组件开始 一&#xff1a;组件需求分析 本次封装组件&#xff0c;主要是摸索封装组件的流程&#xff0c;…

哪个mac虚拟机软件好?怎么选择

虚拟机软件可以说是部分苹果用户们都会使用到的&#xff0c;因为很多软件在Mac上并不兼容&#xff0c;大部分都是基于Windows的框架进行开发设计的。虽然也有出Mac版本&#xff0c;但往往推迟得比较久才会进行发布。 拥有了虚拟机软件之后&#xff0c;我们就能够虚拟想要的系统…

lenovo联想笔记本ThinkPad P16V Gen 1(21FC,21FD)原装出厂Win11系统

原厂W11系统自带所有驱动、出厂主题壁纸、Office办公软件、联想电脑管家等预装程序 链接&#xff1a;https://pan.baidu.com/s/17dTExDSz-EDN4Qd-PZGJuw?pwdrgl3 提取码&#xff1a;rgl3 所需要工具&#xff1a;32G或以上的U盘 文件格式&#xff1a;ISO 文件大小…

油猴插件(Tampermonkey)的使用教程

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 “油猴插件” 与 “油猴扩展程序” 表示同一个意思&#xff0c;下面统一使用“油猴插件”这个名词。 油猴插件的简介 浏览器插件&#xff0c;包括油猴插件和其他插件&#xff0c;通过它们可以实现浏览器网…

Vue 路由守卫详细介绍与演示

Vue 路由守卫是一种在 Vue.js 应用程序中控制路由导航的机制&#xff0c;它允许你在路由变化前、后或在特定路由上执行代码&#xff0c;以便实现诸如权限控制、数据加载、页面切换动画等功能。在下面的介绍中&#xff0c;我将首先提供官方定义和通俗解释&#xff0c;然后详细介…

rosbag 包转TUM数据集

参考链接&#xff1a; ROS学习&#xff1a;制作自己的TUM数据集 配置环境 1.安装ROS 参考我的博客 https://blog.csdn.net/qin_liang/article/details/127035615 2.查看rosbag中的topic rosbag info xxx.bag3.创建catkin_ws/src文件夹 在src下运行 catkin_create_pkg rosb…

<OpenCV> Mat属性

OpenCV的图像数据类型可参考之前的博客&#xff1a;https://blog.csdn.net/thisiszdy/article/details/120238017 OpenCV-Mat类型的部分属性如下&#xff1a; size&#xff1a;矩阵的大小&#xff0c; s i z e ( c o l s , r o w s ) size(cols,rows) size(cols,rows)&#xf…

如何维持股市稳定?——股市定海神针

中国股市于1989年 开始&#xff0c;至今2023年&#xff0c; 已有30多个年头。而这30多年来&#xff0c;却有20多年钟情于3000点。 股市有赌性在&#xff0c;却也为数以千计的企业提供了养料&#xff0c;更关系着数以亿计的股民、以及企业员工的切身利益。 股市3000点&#xff…

(翻译)JavaFX高级教程:JavaFX2.0的FXML语言

原文地址http://download.oracle.com/javafx/2.0/fxml_get_started/jfxpub-fxml_get_started.htm FXML是JavaFX 2.0新引入的。你可能会问"What is FXML?" 和"Is FXML for me?" FXML 是基于XML的一种声明性标记语言&#xff0c;用来定义应用的用户接口。F…

区间DP 计数类DP 数位统计DP 状态压缩DP 树形DP 记忆化搜索

目录 区间DP石子合并分析思路代码实现 计数类DP整数划分完全背包DP的解法二维数组实现一维优化实现 另类DP状态表示的解法&#xff08;分拆数&#xff09;二维数组实现一维优化实现 数位统计DP计数问题注意代码实现 状态压缩DP蒙德里安的梦想实现思路朴素实现预处理优化实现 最…

【视频图像篇】FastStone Capture屏幕长截图软件

【视频图像篇】FastStone Capture屏幕长截图软件 FastStone Capture最常用的一款屏幕长截图软件—【蘇小沐】 文章目录 【视频图像篇】FastStone Capture屏幕长截图软件实验环境1、启动界面2、自定义工具栏3、自动保存 &#xff08;一&#xff09;长截图1、捕获滚动窗口2、捕获…

LINUX 文件基本管理

一、文件类型和根目录结构 1、文件类型 可以通过 ls -l 或者 ll来查看文件类型 可以根据显示&#xff0c;查看第一个字符&#xff0c;就表示文件类型。 - 字符&#xff1a;普通文件&#xff0c;类似于Windows的记事本。 d 字符&#xff1a;目录文件&#xff0c;类似于Wind…

认识异常【超详细】

文章目录 1. 异常的概念与体系结构1.1 异常的概念1.2 异常的体系结构1.3 异常的分类1. 编译时异常2. 运行时异常 2. 异常的处理2.1 防御式编程2.2 异常的抛出2.3 异常的捕获2.3.1 异常声明throws2.3.2 try-catch捕获并处理2.3.3 finally 2.4 异常的处理流程 3. 自定义异常类 1.…

常见缺少msvcp140.dll问题及解决方法,分享多种方法帮你解决

在日常使用电脑的过程中&#xff0c;我们可能会遇到各种问题&#xff0c;比如电脑提示msvcp140.dll文件丢失。这个问题通常是由于某些程序或游戏需要这个dll文件来正常运行&#xff0c;但是由于某种原因&#xff0c;这个文件被误删或者损坏了。那么&#xff0c;如何解决这个问题…

FFmpeg入门之简单介绍

FFmpeg是什么意思: Fast Forward Moving Picture Experts Group ffmpeg相关文档: Documentation FFmpeg ffmpeg源码下载: https://git.videolan.org/git/ffmpeg.git https://github.com/FFmpeg/FFmpeg.git FFmpeg能做什么? 多种媒体格式的封装与解封装 : 1.多种音…