MybatisPlus实战笔记
概述
Mybatis支持定制化SQL、存储过程以及高级映射,避免几乎所有的 JDBC 代码和手动设置参数以及获取结果集。可以使用简单的 XML 或注解来配置和映射原生信息,将接口和Java的POJO映射成数据库中的记录。
缺点:
SQL工作量很大,尤其是字段较多时。单表的增删改查操作可以通过mybatis generator工具来生成(或自己写模板工具生成),但项目开发的过程中总免不了要新添加新字段,得把新字段写到原来的所有增删改查的sql中。
mybatis的单表操作比较麻烦,因为筛选的条件可能会各种各样,所以不得不写很多动态sql来兼容查询条件。
MybatisPlus(简称MP)的出现,可以一定程度上优化上述问题,MP集Mybatis与Hibernate的优点。提供Hibernate的单表CRUD操作的方便同时,又保留Mybatis的特性。在Mybatis的基础上只做增强不做改变,为简化开发、提高效率而生。
特点:
- 无侵入:只做增强不做改变
- 损耗小:启动即自动注入基本CRUD,直接面向对象操作
- 强大的CRUD操作:内置通用Mapper、Service,通过少量配置即可实现单表大部分CRUD操作,还有条件构造器
- 支持多种数据库:
- 支持Lambda形式调用:
- 支持主键自动生成:4中主键策略(包括分布式唯一ID生成器-Sequence),可以自由配置,解决主键问题
- 支持XML热加载:
mapper.xml
支持热加载,简单的CRUD操作无需重启,甚至支持无XML启动 - 支持ActiveRecord模式
- 内置代码生成器:
- 支持关键词自动转义:
- 支持自定义全局通用操作:
- 解除SQL与程序代码的耦合
- 提供映射标签
- 提高对象关系映射标签
- 通过xml标签,支持编写动态SQL
具体的:
架构
架构原理,可参考
功能
注解
@TableId
, 用于主键,MP 支持4种主键策略 IdType
@TableName
,用于表名
@TableField
,字段,exist=true/false,是否对应数据表字段
@Version
,乐观锁标记
@KeySequence
,序列主键策略,主要
@TableLogic
,用于逻辑删除的字段
全局配置 GlobalConfiguration
需要注入到MybatisSqlSessionFactoryBean里面,才能生效
dbColumnUnderline,MP2.3默认为true
idType配置后无需对所有的主键加注解
tablePrefix,仅适用于所有表名前缀相同的情况下
直接获取主键值,无需任何配置,基于BaseMapper
Mapper,顶级Mapper,继承该接口后,无需编写mapper.xml
文件,即可获得CRUD功能,支持 id 泛型
insertAllColumn(); // 无需对全部字段进行setter,然后反应到DB层,落值为null
insert(); // 对全部字段有非空判断
updateById();
updateAllColumnById(); // 没有setter时会覆盖原有数据为null
T selectById(Serializable id);
T selectOne(@Param("ew") T entity);
List<T> selectBatchIds(List<? extends Serializable> idList);
List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
List<T> selectPage(RowBounds rowBounds, @Param("ew") Wrapper<T> wrapper);
RowBounds,分页查询条件,SQL语句没有limit关键字,不是真实的物理分页?!
Page,分页辅助类,
分页插件
Spring Boot配置方式:
@Bean
public PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();
}
UserMapper.java:
List<User> getList(Pagination page, Integer status);
UserServiceImpl.java
调用分页方法,需要page.setRecords
回传给页面:
public Page<User> getList(Page<User> page, Integer status) {return page.setRecords(userMapper.getList(page, status));
}
Mybatis PageHelper对比MP PaginationInterceptor
Mybatis PageHelper是独立于Mybatis的依赖包,需要引入多个maven依赖。而MP PaginationInterceptor是MP自带插件,是否启用插件取决于是否配置。底层原理都是使用拦截器实现。
公共字段自动填充
平时在建对象表时都会有最后修改时间last_update_time
,最后修改人last_update_name
这两个字段,对于这些大部分表都有的字段,每次在新增和修改的时候都要考虑到这几个字段有没有传进去,很麻烦。
MybatisPlus公共字段自动填充的功能可以解决此问题。一般满足下面条件的字段就可以使用此功能:
- 这个字段是大部分表都会有的。
- 这个字段的值是固定的,或则字段值是可以在后台动态获取的。
MybatisPlus 2.0.6版本支持更新数据公共字段自动填充,之前都是只支持新增数据的时候可以使用。
配置:
继承IMetaObjectHandler抽象类,实现两个方法,insertFill()
用于新增数据时需要填充的字段,updateFill()
用于更新数据时需要填充的字段:
import org.apache.ibatis.reflection.MetaObject;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Component;
import com.baomidou.mybatisplus.mapper.MetaObjectHandler;
/** mybatisplus自定义填充公共字段, 即没有传的字段自动填充*/
@Component
public class MyMetaObjectHandler extends MetaObjectHandler {// 新增填充@Overridepublic void insertFill(MetaObject metaObject) {Object lastUpdateNameId = metaObject.getValue("lastUpdateNameId");Object lastUpdateTime = metaObject.getValue("lastUpdateTime");// 获取当前登录用户SysUser user = (SysUser)SecurityUtils.getSubject().getPrincipal();if (null == lastUpdateNameId) {metaObject.setValue("lastUpdateNameId", user.getId());}if (null == lastUpdateTime) {metaObject.setValue("lastUpdateTime", new Date());}}// 更新填充@Overridepublic void updateFill(MetaObject metaObject) {insertFill(metaObject);}
}
getValue()
方法的参数是POJO类里面的变量(驼峰的命名方式)。
在MybatisPlus的配置文件中公共字段生成类的bean:
// 全局配置
GlobalConfiguration globalConfig = new GlobalConfiguration();
// 配置公共字段自动填写
globalConfig.setMetaObjectHandler(new MyMetaObjectHandler());
也就是将刚刚写的公共字段填充的设置设置到MP全局配置的对象中。
填充的字段需要忽略验证,在表对象pojo类的对应属性上添加下面注解:
@TableField(value = "last_update_id", validate = FieldStrategy.NOT_EMPTY)
private String lastUpdateNameId;
@TableField(value = "last_update_time", validate = FieldStrategy.NOT_EMPTY)
private Date lastUpdateTime;
原因:因为调用更新和插入的方法时,会验证你所传的属性是否为空,来判断是否该更新和插入这个属性,这个就和公共字段自动填充相冲突,所以需要这个注解来标识此属性不需要验证。不然在插入的时候就会填充失败。
测试
// 公共字段自动填充
// 1.在mybatisplus的配置文件中公共字段生成类的bean
// 2.实现IMetaObjectHandler类
// 3.忽略对应字段的为空检测,在pojo类的属性上添加@TableField(value="last_update_name_id",validate=FieldStrategy.IGNORED)
@Test
public void publicTest(){SysUser user = new SysUser();sysUserService.insert(user);sysUserService.selectById(user.getId());SysUser user1 = new SysUser();user1.setId(user.getId());sysUserService.updateById(user1);sysUserService.selectById(user.getId());
}
本来是打算创建人和创建时间,也使用这种方法处理的,最后发现,如果将这两个字段也忽略为空的判断,也就是加上validate=FieldStrategy.NOT_EMPTY
,在更新数据的时候会将创建人和创建时间一起更新,不传的话就会更新为空。但是在正真用的上的需求上面使用的时候还不够完善。
逻辑删除
使用此插件后的效果:
- 在mp自带查询和更新方法的SQL后面,追加
<逻辑删除字段>=<LogicNotDeleteValue默认值>
- 删除方法: deleteById()和其他delete方法,底层SQL为:
update tbl_xxx set <逻辑删除字段>=<logicDeleteValue默认值>
配置如下:
- 修改集成全局注入器为 LogicSqlInjector
application.yml
全局注入值:logicDeleteValue // 逻辑删除全局值 logicNotDeleteValue // 逻辑未删除全局值
自定义注入器的一种,
需要@TableLogic
问题:不能配置多个AutoSqlInjector注入器?
支持XML热加载
在使用MyBatis本地开发时,需要经常性地修改调整mapper.xml
文件。IDEA虽然自带热更新(热加载)功能,但是对于mapper.xml
文件却不奏效,也就是说在修改mapper.xml
文件后,需要重启应用。
哪怕应用足够轻量级或者优化得足够好,启动也需要好几秒时间。此时有个mapper.xml
文件热加载功能就可以提高开发效率。
经过调研,是可以实现的,参考:MyBatis系列之mapper.xml实现热加载HotSwap。
而MP自带mapper.xml
文件热加载功能。
模糊查询
like
notlike
likeLeft
likeRight
代码生成
配置好generator.properties
文件:
# 包前缀
package=com.github
# 模块名
moduleName=shop
# 作者名
author=johnny
email=
# 表前缀,如表tb_sys_user 生成类 sys_user
tablePrefix=m_,r_,s_
# 数据转换类型
tinyint=Boolean
smallint=Integer
mediumint=Integer
int=Integer
integer=Integer
bigint=Long
float=Float
double=Double
decimal=BigDecimal
bit=Boolean
char=String
varchar=String
tinytext=String
text=String
blob=String
mediumtext=String
longtext=String
date=Date
datetime=Date
timestamp=Date
定义好velocity模板文件(pom文件需要引入velocity依赖),从数据表PO实体类到Controller接口方法都支持自动生成:Model.java.vm
、Mapper.java.vm
、Mapper.xml.vm
、Service.java.vm
、ServiceImpl.java.vm
、Controller.java.vm
。
如:
package ${package}.${moduleName}.model;import ${package}.common.model.SuperEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
#if(${hasBigDecimal})
import java.math.BigDecimal;
#end
import java.util.Date;/*** ${comments}** @author ${author}*/
@Data
@TableName("${tableName}")
public class ${className} extends SuperEntity {#foreach ($column in $columns)#if($column.columnName != $pk.columnName && $column.columnName != "createTime" && $column.columnName !="updateTime")private $column.attrType $column.attrname;#end
#end
}
其他
执行分析,性能分析,乐观锁,XML热加载,自定义全局操作,逻辑删除,读写分离&多数据源,主键Sequence,多租户SQL解析器,通用枚举自动注入,IDEA快速开发;
条件构造器
EntityWrapper/Condition,都是基于Wrapper,Wrapper抽象类的方法:
.last()
有SQL注入的风险
AR
Active Record,一种数据访问设计模式,它可以帮助你实现数据对象Object到关系数据库的映射。
Model,实现pkVal抽象方法,指定当前实体类的主键属性
EntityWrapper,支持泛型,builder模式,
不用注入aaaMapper,
AutoGenerator
Oracle 主键问题
使用@KeySequence解决,用在实体类上,
数据库层面:
create sequence seq_user start with 100 increment by 2;
-- 查询序列的下一个值
select seq_user.nextval from dual;
-- 查询序列的当前值
select seq_user.currval from dual;
2.问题
mybatis-plus怎么实现单表URUD操作?
mybatis-plus的底层实现原理是什么?
mybatis-plus与其他同类框架如mybatis helper有很什么优势?
如何集成mybatis-plus快速搭建一个spring boot项目。
参考
MyBatis-Plus源码分析
相关文章:

MybatisPlus实战笔记
概述 Mybatis支持定制化SQL、存储过程以及高级映射,避免几乎所有的 JDBC 代码和手动设置参数以及获取结果集。可以使用简单的 XML 或注解来配置和映射原生信息,将接口和Java的POJO映射成数据库中的记录。 缺点: SQL工作量很大,尤…...
Android Studio 报错:Failed to create Jar file xxxxx.jar
通过分析,新下载的项目没有project/gradle目录,故通过其他项目复制到当前项目,就解决了该问题。 同时也出现了新的问题 Unable to start the daemon process.The project uses Gradle 4.1 which is incompatible with Java 11 or newer.原因…...

Django实现音乐网站 ⑸
使用Python Django框架制作一个音乐网站, 本篇主要是配置媒体资源设置。 目录 配置介绍 设置媒体资源 创建媒体资源目录 修改settings.py 注册媒体资源路由 总结 配置介绍 静态资源是指项目配置的js/css/image等系统常用文件。对于一些经常变动的资源&#x…...

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)七:工作台界面实现
一、本章内容 本章实现工作台界面相关内容,包括echart框架引入,mock框架引入等,实现工作台界面框架搭建,数据加载。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频 基于VUE3+Layui从头搭建通用后台管理系统合集-工作台界面布局实现 五、…...

前端vue uni-app自定义精美海报生成组件
在当前技术飞速发展的时代,软件开发的复杂度也在不断提高。传统的开发方式往往将一个系统做成整块应用,一个小的改动或者一个小功能的增加都可能引起整体逻辑的修改,从而造成牵一发而动全身的情况。为了解决这个问题,组件化开发逐…...

高通滤波器,低通滤波器
1.高通滤波器是根据像素与邻近像素的亮度差值来提升该像素的亮度。 import cv2 import numpy as np from scipy import ndimagekernel_3_3 np.array([[-1,-1,-1],[-1,8,-1],[-1,-1,-1]]) print(kernel_3_3) kernel_5_5 np.array([[-1,-1,-1,-1,-1],[-1,1,2,1,-1],[-1,2,4,2,-…...

机器学习深度学习——卷积的多输入多输出通道
👨🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习&&深度学习——从全连接层到卷积 📚订阅专栏:机器学习&&深度学习 希望文章对你们有所帮…...

HTML5中Canvas学习笔记:Canvas
目录 一、HTML中Canvas画图strokeStyle 和 fillStyle 的区别是什么? 二、如何设置一幅canvas图中某个颜色透明? 三、H5 canvas中strokeRect参数如果是小数,如何处理? 四、H5 Canvas中如何画圆角矩形框? 一、HTML中…...

Windows安装子系统Linux
Windows安装子系统(Linux ubuntu) 安装条件步骤1.安装WSL命令2.设置Linux用户名和密码3.写个简单的.c程序看看4.如何互传文件 安装条件 Windows 10版本2004及更高的版本才能安装。 步骤 1.安装WSL命令 我们可以使用WSL来安装子系统 Linux ubuntu(默认是这个)。 …...

C 语言的 pow() 函数
作用: Calculates x raised to the power of y. 函数原型: double pow( double x, double y ); Required Header: <math.h> Compatibility: ANSI Return Value pow returns the value of x y x^{y} xy. No error message is printed on overflow or underflow. Paramete…...

socket 基础
Socket是什么呢? ① Socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过“套接字”向网络发出请求或者应答网络请求。 ② Socket是连接运行在网络上的两个程序间的双向通信的端点。 ③ 网络通讯其实指…...
JMeter(二十五)、一些概念的理解---90%响应时间、事务、并发
Jmeter中一些概念的理解——90%响应时间、事务、并发 一、90%响应时间(参考虫师博客) 90%Line 一组数由小到大进行排列,找到他的第90%个数(假如是12),那么这个数组中有90%的数将小于等于12 。 用在性能测试的响应时间,也就是90%请求响应时间不会超过12 秒。 例如:…...

直播课 | 大橡科技研发总监丁端尘博士“类器官芯片技术在新药研发中的应用”
从类器官到类器官芯片,正在生物科学领域大放异彩。 药物研发需要新方法 众所周知,一款新药是一个风险大、周期长、成本高的艰难历程,国际上有一个传统的“双十”说法——10年时间,10亿美金,才可能成功研发出一款新药…...

Python中的PDF文本提取:使用fitz和wxPython库(带进度条)
引言: 处理大量PDF文档的文本提取任务可能是一项繁琐的工作。本文将介绍一个使用Python编写的工具,可通过简单的操作一键提取大量PDF文档中的文本内容,极大地提高工作效率。 import wx import pathlib import fitzclass PDFExtractor(wx.Fr…...
mysql 将字段值+1或自增
一、解决方式: SET var 1; UPDATE jes_menu_info SET MENU_SORT (var : var 1) WHERE ss_idACC; 二、解读用户变量,在客户端链接到数据库实例整个过程中用户变量都是有效的。 MySQL中用户变量不用事前申明,在用的时候直接用“变量名”使…...

组合总和——力扣39
文章目录 题目描述回溯 题目描述 回溯 class Solution { public:vector<vector<int>> res;vector<int> seq; void dfs(vector<int>& nums, int pos, int target){if(target0){res.emplace_back(seq);return;}if(posnums.size()){return;}//直接跳过…...

PostgreSQL Patroni_exporter 监控 patroni高可用工具
Patroni是Cybertec公司基于python语言开发的,可用于使用流复制来创建,管理,维护和监视高可用性PostgreSQL集群设置的工具。 目前,PatroniEtcd 是最为推荐的PostgreSQL数据库高可用方案之一。 PostgreSQL有postgres_exporter监控采…...

C语言多级指针
#include "stdio.h" #include <stdlib.h>int main() {int a 10;//*p int a int *pint* p &a;int** q &p;//int** q int *(*q) int *(q) a//int**q int*(*q) int*(&a) int*&a aint*** k &q;//分析:首先k是个变量&…...

IDEA项目实践——创建Java项目以及创建Maven项目案例、使用数据库连接池创建项目简介
系列文章目录 IDEA上面书写wordcount的Scala文件具体操作 IDEA创建项目的操作步骤以及在虚拟机里面创建Scala的项目简单介绍 目录 系列文章目录 前言 一 准备工作 1.1 安装Maven 1.1.1 Maven安装配置步骤 1.1.2 解压相关的软件包 1.1.3 Maven 配置环境变量 1.1.4 配…...

ArraySetter
简介 用来展示属性类型为数组的 setter 展示 配置示例 "setter": {"componentName": "ArraySetter","props": {"itemSetter": {"componentName": "ObjectSetter","props": {"c…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...

C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...

深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学
一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件,其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时,价带电子受激发跃迁至导带,形成电子-空穴对,导致材料电导率显著提升。…...

如何优雅地绕过限制调用海外AI-API?反向代理与API中转技术详解
阅读时长 | 8分钟 适用读者 | 需要跨境调用OpenAI等AI服务的开发者/企业 一、问题背景:为什么需要代理? 最近在技术社区看到这样的求助: "公司服务器在国内,但业务需要调用OpenAI接口,直接访…...

奈飞工厂官网,国内Netflix影视在线看|中文网页电脑版入口
奈飞工厂是一个专注于提供免费Netflix影视资源的在线播放平台,致力于为国内用户提供的Netflix热门影视内容。该平台的资源与Netflix官网基本同步,涵盖电影、电视剧、动漫和综艺等多个领域。奈飞工厂的界面简洁流畅,资源分类清晰,方…...