探索MyBatis-Plus的高阶用法

引言

MyBatis-Plus 是 MyBatis 的增强工具包,提供了许多方便快捷的功能来简化开发,提高效率。除了基本的 CRUD 操作外,MyBatis-Plus 还提供了一些高级功能,本文将探讨 MyBatis-Plus 的高阶用法,帮助开发者更好地利用该工具包。

1. 动态表名和字段

MyBatis-Plus 支持动态表名和字段,这在一些特殊场景下非常有用,比如多租户系统或者动态数据源切换。通过注解 @TableName@TableField 可以动态指定表名和字段名。

@TableName("user_${dynamicValue}")
public class User {@TableField(value = "name_${dynamicValue}")private String name;
}

2. 自定义全局操作

MyBatis-Plus 允许自定义全局操作,比如自定义全局的查询条件、插入前操作、更新前操作等。通过实现 com.baomidou.mybatisplus.core.injector.ISqlInjector 接口可以实现自定义 SQL 注入器,通过实现 com.baomidou.mybatisplus.core.handlers.MetaObjectHandler 接口可以实现字段自动填充等。

@Component
public class CustomMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class);}@Overridepublic void updateFill(MetaObject metaObject) {this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);}
}

3. 自动分页

MyBatis-Plus 提供了自动分页的功能,可以自动根据查询条件进行分页,无需手动编写分页 SQL。只需在查询条件中添加分页参数即可。

Page<User> page = new Page<>(1, 10);
userMapper.selectPage(page, null);

4. 逻辑删除

MyBatis-Plus 支持逻辑删除,通过注解 @TableLogic 可以指定逻辑删除字段,并在查询时自动过滤掉已被逻辑删除的记录。

@Configuration
@MapperScan("com.example.mapper")
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new LogicSqlInjector());interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}@Beanpublic ISqlInjector sqlInjector() {return new LogicSqlInjector();}
}
@TableLogic
@TableField(value = "is_deleted")
private Integer deleted;
// 执行逻辑删除
userMapper.deleteById(userId);// 查询用户列表,自动过滤已被逻辑删除的记录
List<User> userList = userMapper.selectList(null);

5. 实现多租户系统

在多租户系统中,不同的租户需要访问不同的数据,但数据结构相同。通过动态表名可以很方便地实现多租户数据的隔离存储。

@TableName("user_${tenantId}")
public class User {@TableField(value = "name")private String name;
}

根据不同的租户(tenantId),用户数据将存储在不同的表中,实现了多租户数据的隔离存储。 

 

6. 动态数据源切换

在一些特殊的场景中,需要根据不同的条件切换数据源。通过动态表名和字段可以很方便地实现动态数据源切换。

@TableName("user_${dataSource}")
public class User {@TableField(value = "name_${dynamicValue}")private String name;
}

7. 数据权限控制

在一些需要进行数据权限控制的系统中,不同的用户可能只能访问部分数据。通过动态表名和字段可以很方便地实现数据权限控制。

@TableName("user_${roleId}")
public class User {@TableField(value = "name_${dynamicValue}")private String name;
}

根据不同的用户角色(roleId),用户数据将存储在不同的表中,并且字段名也会动态变化,实现数据权限控制的需求。 

 

8. 分表分库

在数据量较大的系统中,为了提高性能和扩展性,可能会采用分表分库的方式来存储数据。通过动态表名和字段可以很方便地实现分表分库。

@TableName("user_${shardingValue}")
public class User {@TableId(type = IdType.AUTO)private Long id;private String username;private Integer age;// 其他字段...
}

 分库分表策略配置

@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 配置分页插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));// 配置分片插件interceptor.addInnerInterceptor(new DynamicTableNameInnerInterceptor());return interceptor;}@Beanpublic DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor() {return new DynamicTableNameInnerInterceptor();}
}

分库分表策略实现 

public class DynamicTableNameInnerInterceptor extends InnerInterceptor {@Overridepublic void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {if (parameter instanceof Map) {Map<?, ?> paramMap = (Map<?, ?>) parameter;ShardingValue shardingValue = (ShardingValue) paramMap.get("shardingValue");if (shardingValue != null) {String tableName = "user_" + shardingValue.getValue() % 2; // 根据分片值计算表名String sql = boundSql.getSql().replaceFirst("user", tableName); // 替换原始 SQL 中的表名ReflectionUtils.setField(boundSql, "sql", sql); // 修改 BoundSql 中的 SQL}}}
}

9. 动态 SQL

在一些复杂的业务场景中,可能需要根据不同的条件动态生成 SQL,比如动态拼接 WHERE 子句、动态排序等。MyBatis-Plus 提供了方便的 API 来实现动态 SQL。

QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("status", status);
if (StringUtils.isNotBlank(keyword)) {wrapper.like("name", keyword);
}
wrapper.orderByDesc("create_time");
List<User> userList = userMapper.selectList(wrapper);

10. 乐观锁

在并发场景下,为了保证数据的一致性,可能会使用乐观锁机制来控制并发访问。MyBatis-Plus 提供了乐观锁的支持,通过 @Version 注解标注实体类中的版本字段即可实现乐观锁功能。

@Version
@TableField(value = "version")
private Integer version;

11. 逻辑分页

在一些特殊的场景中,可能需要进行复杂的分页操作,比如根据某个字段的范围进行分页查询。MyBatis-Plus 提供了逻辑分页的功能,通过 last() 方法可以实现自定义的分页逻辑。根据年龄大于等于 18 并按照创建时间降序排列的条件进行分页查询

IPage<User> page = new Page<>(1, 10);
userMapper.selectPage(page, Wrappers.<User>lambdaQuery().ge(User::getAge, 18).orderByDesc(User::getCreateTime).last("limit 10"));

12. 代码生成器        

public class CodeGenerator {public static void main(String[] args) {AutoGenerator generator = new AutoGenerator();// 配置数据源、包配置、策略配置等generator.execute();}
}

结语

MyBatis-Plus 是一个非常优秀的 MyBatis 增强工具包,它在简化开发、提高效率、提升性能等方面都有着显著的优势,是开发中不可或缺的利器。希望本文对读者对 MyBatis-Plus 的了解有所帮助,欢迎大家深入学习和使用 MyBatis-Plus。

 

更多文章


​​Spring中的事务是如何实现的-CSDN博客

ZooKeeper 使用介绍和原理详解-CSDN博客

Redis集群选举流程详解-CSDN博客

Hadoop技术解析:分布式存储与计算-CSDN博客

ES底层原理深度剖析_es 的底层原理-CSDN博客

 

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

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

相关文章

Linux服务器搭建超简易跳板机连接阿里云服务器

简介 想要规范内部连接阿里云云服务器的方式&#xff0c;但是最近懒病犯了&#xff0c;先搞一个简易式的跳板机过渡一下&#xff0c;顺便在出一个教程&#xff0c;其他以后再说&#xff01; 配置方法 创建密钥 登录阿里云&#xff0c;找到云服务器ECS控制台&#xff0c;点击…

【小白友好】LeetCode 打家劫舍 III

https://leetcode.cn/problems/house-robber-iii/description/ 前言 建议还是先看看动态规划的基础题再看这个。动态规划是不刷题&#xff0c;自己100%想不出来的。 基础题&#xff1a; 23 小白想法 现在我们想遍历的数据结构不是数组了&#xff0c;而是一颗树。在树上的d…

C++递推

统计每个月兔子的总数 #include<bits/stdc.h> using namespace std; int n,sum0; void f(int); int main() {int a[1000];cin>>n;a[1]1;a[2]2;for(int i3;i<1000;i){a[i]a[i-1]a[i-2];}cout<<a[n];return 0; } void f(int n){}猴子吃桃子 #include<b…

2024年华为OD机试真题-电脑病毒感染-Python-OD统一考试(C卷)

题目描述: 一个局域网内有很多台电脑,分别标注为0 - N-1的数字。相连接的电脑距离不一样,所以感染时间不一样,感染时间用t表示。 其中网络内一个电脑被病毒感染,其感染网络内所有的电脑需要最少需要多长时间。如果最后有电脑不会感染,则返回-1 给定一个数组times表示一个…

在Spring Boot中如何实现异常处理?

在Spring Boot中&#xff0c;异常处理可以通过几种方式实现&#xff0c;以提高应用程序的健壮性和用户体验。这些方法包括使用ControllerAdvice注解、ExceptionHandler注解、实现ErrorController接口等。下面是一些实现Spring Boot异常处理的常用方法&#xff1a; 1. 使用Cont…

Git实战(2)

git work flow ------------------------------------------------------- ---------------------------------------------------------------- 场景问题及处理 问题1&#xff1a;最近提交了 a,b,c,d记录&#xff0c;想把b记录删掉其他提交记录保留&#xff1a; git reset …

【C++ 编程指南】

C 编程指南 ■ C环境安装■ C 基本语法■ 预定义宏■ # 和 ## 运算符■ C 引用■ C 命名空间■ 定义命名空间■ using 指令■ 嵌套的命名空间 ■ String类■ 类■ 类的static静态成员 ■ C 继承■ 继承类型 public、protected 或 private■ 访问控制和继承■ 多继承■ 数据抽象…

机器学习-面经

经历了2023年的秋招&#xff0c;现在也已经入职半年了&#xff0c;空闲时间将面试中可能遇到的机器学习问题整理了一下&#xff0c;可能答案也会有错误的&#xff0c;希望大家能指出&#xff01;另外&#xff0c;不论是实习&#xff0c;还是校招&#xff0c;都祝福大家能够拿到…

990-28产品经理:Different types of IT risk 不同类型的IT风险

Your IT systems and the information that you hold on them face a wide range of risks. If your business relies on technology for key operations and activities, you need to be aware of the range and nature of those threats. 您的IT系统和您在其中持有的信息面临…

数据结构c版(2)——二叉树

本章我们来了解一下二叉树这一概念。 目录 1.树概念及结构 1.1树的概念​​​​​​​ 1.2 树的特点&#xff1a; 1.3 树的相关概念 1.4 树的表示​​​​​​​ 1.5 树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 2.二叉树概念及结构 2.1概念 …

Qt 简约美观的动画 摆钟风格 第十季

&#x1f60a; 今天给大家分享一个摆钟风格的加载动画 &#x1f60a; 效果如下: 最近工作忙起来了 , 后续再分享其他有趣的加载动画吧. 一共三个文件 , 可以直接编译运行 //main.cpp #include "LoadingAnimWidget.h" #include <QApplication> #include <Q…

【C++】用文件流的put和get成员函数读写文件

题目 编写一个mycopy程序&#xff0c;实现文件复制的功能。用法是在控制台输入&#xff1a; mycooy 源文件名 目标文件名 参数介绍 m a i n main main 函数的参数有两个&#xff0c;一个int类型参数和一个指针数组。 a r g c argc argc 表示参数的个数。参数为void时 a r g …

机器人 标准DH与改进DH

文章目录 1 建立机器人坐标系1.1 连杆编号1.2 关节编号1.3 坐标系方向2 标准DH(STD)2.1 确定X轴方向2.2 建模步骤2.3 变换顺序2.4 变换矩阵3 改进DH(MDH)3.1 确定X轴方向3.2 建模步骤3.3 变换顺序3.4 变换矩阵4 标准DH与改进DH区别5 Matlab示例参考链接1 建立机器人坐标系 1.1…

Elasticsearch:如何创建搜索引擎

作者&#xff1a;Jessica Taylor 搜索引擎是生活中我们认为理所当然的事情之一。 每当我们寻找某些东西时&#xff0c;我们都会将一个单词或短语放入搜索引擎&#xff0c;就像魔术一样&#xff0c;它会为我们提供一个匹配结果列表。 现在可能感觉不那么神奇了&#xff0c;因为这…

Go-知识struct

Go-知识struct 1. struct 的定义1.1 定义字段1.2 定义方法 2. struct的复用3. 方法受体4. 字段标签4.1 Tag是Struct的一部分4.2 Tag 的约定4.3 Tag 的获取 githupio地址&#xff1a;https://a18792721831.github.io/ 1. struct 的定义 Go 语言的struct与Java中的class类似&am…

第二十三章 :Docker 部署 Redis

第二十三章 :Docker Redis 部署 Docker version 25.0.3, build 4debf41 ,Docker Compose version v2.24.2Redis-6.0.6 镜像 redis:6.0.6-alpineRedis-6.0.6版本 部署规划 服务器IP192.168.92.105端口6379安装目录/home/work/docker-redis-6.0.6数据映射目录/home/work/do…

最简单的基于 FFmpeg 的收流器(以接收 RTMP 为例)

最简单的基于 FFmpeg 的收流器&#xff08;以接收 RTMP 为例&#xff09; 最简单的基于 FFmpeg 的收流器&#xff08;以接收 RTMP 为例&#xff09;正文结果工程文件下载参考链接 最简单的基于 FFmpeg 的收流器&#xff08;以接收 RTMP 为例&#xff09; 参考雷霄骅博士的文章…

蓝凌OA frpt_listreport_definefield.aspx接口存在SQL注入漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

DevStack 部署 OpenStack

Devstack 简介 DevStack 是一系列可扩展的脚本&#xff0c;用于基于 git master 的最新版本快速调出完整的 OpenStack 环境。devstack 以交互方式用作开发环境和 OpenStack 项目大部分功能测试的基础。 devstack 透过执行 stack.sh 脚本&#xff0c;搭建 openstack 环境&…

lv20 QT主窗口4

熟悉创建主窗口项目 1 QAction 2 主窗口 菜单栏&#xff1a;fileMenu menuBar()->addMenu(tr("&File")); 工具栏&#xff1a;fileToolBar addToolBar(tr("File")); 浮动窗&#xff1a;QDockWidget *dockWidget new QDockWidget(tr("Dock W…