MybatisPlus实战笔记

news2024/9/27 23:32:04

概述

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  {
    // 新增填充
    @Override
    public 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());
        }
    }
    // 更新填充
    @Override
    public 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,在更新数据的时候会将创建人和创建时间一起更新,不传的话就会更新为空。但是在正真用的上的需求上面使用的时候还不够完善。

逻辑删除

使用此插件后的效果:

  1. 在mp自带查询和更新方法的SQL后面,追加<逻辑删除字段>=<LogicNotDeleteValue默认值>
  2. 删除方法: deleteById()和其他delete方法,底层SQL为:update tbl_xxx set <逻辑删除字段>=<logicDeleteValue默认值>

配置如下:

  1. 修改集成全局注入器为 LogicSqlInjector
  2. 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.vmMapper.java.vmMapper.xml.vmService.java.vmServiceImpl.java.vmController.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源码分析

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

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

相关文章

结构体和 Json 相互转换(序列化反序列化)

关于 JSON 数据 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也 易于机器解析和生成。RESTfull Api 接口中返回的数据都是 json 数据。 Json 的基本格式如下&#xff1a; { "a": "Hello", "b": "…

DC-2靶机

文章目录 信息收集漏洞发现漏洞利用 DC-2介绍 DC-2环境下载 请注意&#xff0c;您需要将渗透测试设备上的 hosts 文件设置为&#xff1a; 192.168.0.145 dc-2 显然&#xff0c;将 192.168.0.145 替换为 DC-2 的实际 IP 地址。 它将使生活变得更加简单&#xff08;如果没有它&am…

【Linux】从0到1实现一个进度条小程序

个人主页&#xff1a;&#x1f35d;在肯德基吃麻辣烫 我的gitee&#xff1a;gitee仓库 分享一句喜欢的话&#xff1a;热烈的火焰&#xff0c;冰封在最沉默的火山深处 文章目录 前言一、理解回车 \r 和换行 \n二、初步认识缓冲区1. 认识第一个函数&#xff1a;sleep2.观察缓冲区…

固态继电器:电气开关的革命

简介&#xff1a;在电气工程领域&#xff0c;固态技术的发展为各个领域的显着进步铺平了道路。固态继电器 (SSR) 就是其中一项备受关注的创新。与传统机电继电器不同&#xff0c;SSR 采用固态元件&#xff0c;具有许多优点&#xff0c;例如更高的可靠性、更快的响应时间和增强的…

dvwa靶场通关(十)

第十关&#xff1a;DOM Based Cross Site Scripting (XSS) DOM—based XSS漏洞的产生 DOM—based XSS漏洞是基于文档对象模型Document Objeet Model&#xff0c;DOM)的一种漏洞。DOM是一个与平台、编程语言无关的接口&#xff0c;它允许程序或脚本动态地访问和更新文档内容、…

有效的括号字符串(力扣)动态规划、贪心 JAVA

给你一个只包含三种字符的字符串&#xff0c;支持的字符类型分别是 ‘(’、‘)’ 和 ‘*’。请你检验这个字符串是否为有效字符串&#xff0c;如果是有效字符串返回true 。 有效字符串符合如下规则&#xff1a; 任何左括号 ‘(’ 必须有相应的右括号 ‘)’。 任何右括号 ‘)’ …

postgresql表膨胀处理之pgcompacttable部署及使用

环境&#xff1a; 1&#xff09;redhat-release&#xff1a;CentOS Linux release 7.6.1810 (Core) 2&#xff09;database version&#xff1a;postgresql 14.6 一、添加pgstattuple pgcompacttable工具使用过程中需要依赖pgstattuple&#xff0c;因此需先添加pgstattuple…

[C++]01.基础,数据类型,运算符

01.基础,数据类型,运算符 一.C基础入门1.HelloWorld2.注释3.变量4.常量5.关键字6.命名规则 二.数据类型1.整形2.sizeof关键字3.浮点型4.字符型5.转义字符6.字符串型7.布尔类型8.数据的输入 三.运算符1.算数运算符2.赋值运算符3.比较运算符4.逻辑运算符 一.C基础入门 1.HelloWo…

【雕爷学编程】MicroPython动手做(30)——物联网之Blynk 4

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

力扣 C++|一题多解之动态规划专题(1)

动态规划 Dynamic Programming 简写为 DP&#xff0c;是运筹学的一个分支&#xff0c;是求解决策过程最优化的过程。20世纪50年代初&#xff0c;美国数学家贝尔曼&#xff08;R.Bellman&#xff09;等人在研究多阶段决策过程的优化问题时&#xff0c;提出了著名的最优化原理&…

【习题】几道二叉树题目,进来看看你会不?

几道二叉树题目解析 前言正式开始1. 根据二叉树创建字符串&#xff08;力扣606&#xff09;题目描述解析代码 2. 二叉树的层序遍历1&#xff08;力扣102&#xff09;题目描述解析代码 3. 二叉树的层序遍历2&#xff08;力扣107&#xff09;代码 4. 二叉树的最近公共祖先&#x…

接口测试之json中的key获取

在很多情况下我们在进行接口测试的时候都会有获取上个接口返回的json数据中的某个key值&#xff0c;然后下个接口调用这个key值。今天给大家讲解一下针对不同类型的json获取某个key的值。 一、首先是单纯object格式key值获取 获取图中的token的值&#xff0c;首先这是一个响应…

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)【四】

文章目录 SSM(Vue3ElementPlusAxiosSSM前后端分离)--基础环境搭建【四】项目介绍项目功能/界面● SSM 整合项目界面 创建表&#xff0c;使用逆向工程生成Bean、XxxMapper 和XxxMapper.xml1. 创建furns_ssm 数据库和furns 表使用MyBatis Generator 逆向工程生成bean mapper 接口…

基于Jonswap谱的随机波高及波压力生成

内容目录 基于Jonswap谱的随机波高及波压力生成基于Jonswap谱的随机波高及波压力生成 海面高程可视为是平稳高斯随机过程,可通过对波浪谱确定的一系列分量波进行叠加得到。JONSWAP谱是在海洋结构设计和分析中常用的波浪频谱,可以用其来模拟随机波浪。 式中:有义波高H1/3和…

GPIO简介

一、GPIO GPIO&#xff08;General-purpose input/output&#xff09;即通用型输入输出&#xff0c;GPIO可以控制连接在其之上的引脚实现信号的输入和输出 芯片的引脚与外部设备相连&#xff0c;从而实现与外部硬件设备的通讯、控制及信号采集等功能 LED实验步骤 实验步骤 以L…

1. CUDA中的grid和block

1. CUDA中的grid和block基本的理解 Kernel: Kernel不是CPU&#xff0c;而是在GPU上运行的特殊函数。你可以把Kernel想象成GPU上并行执行的任务。当你从主机&#xff08;CPU&#xff09;调用Kernel时&#xff0c;它在GPU上启动&#xff0c;并在许多线程上并行运行。 Grid: 当你…

C高级【day2】

思维导图&#xff1a; 递归实现&#xff0c;输入一个数&#xff0c;输出这个数的每一位&#xff1a; #include<myhead.h>//递归函数 void fun(int num){//num没值不再递归if(0 num){return;}//输出数的最后一位printf("%d\t", num%10);//递归fun(num/10);}…

AI Chat 设计模式:11. 状态模式

本文是该系列的第十一篇&#xff0c;采用问答式的方式展开&#xff0c;问题由我提出&#xff0c;答案由 Chat AI 作出&#xff0c;灰色背景的文字则主要是我的一些思考和补充。 问题列表 Q.1 你知道状态模式吗A.1Q.2 它与有限状态机有什么联系吗&#xff1f;A.2Q.3 知道了&…

Spring:IOC技术、Bean、DI

前言 Spring是一个开源的项目&#xff0c;并不是单单的一个技术&#xff0c;发展至今已形成一种开发生态圈。也就是说我们可以完全使用Spring技术完成整个项目的构建、设计与开发。Spring是一个基于IOC和AOP的架构多层j2ee系统的架构。 SpringFramework&#xff1a;Spring框架…

ROS2学习(四)进程,线程与节点的关系

节点与节点执行器 节点&#xff0c;英文是node,在ROS2中&#xff0c;节点是一个抽象的实体&#xff0c;它可以代表某种或某类特定功能的抽象集合体&#xff0c;它可以存在于进程中&#xff0c;也可以存在于线程中。所有ROS2的基础功能最基础的载体是节点&#xff0c;所有的通信…