【Spring Boot后端组件】mybatis-plus使用

文章目录

  • mybatis-plus使用
    • 一、依赖引入
    • 二、添加相关配置项
    • 三、功能详解
      • 1.自增主键
      • 2.逻辑删除
      • 3.操作时间自动填充
      • 4.其他字段自动填充
      • 5.分页查询
      • 6.自定义动态查询
      • 7.代码生成器
      • 8.代码生成器(自定义模板)

mybatis-plus使用

一、依赖引入

pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.4</version><relativePath/></parent><artifactId>mybatis-plus-demo</artifactId><dependencies><!-- 实现对数据库连接池的自动化配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency> <!-- 本示例,我们使用 MySQL --><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.48</version></dependency><!-- 实现对 MyBatis Plus 的自动化配置 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.2.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies></project>

二、添加相关配置项

application.yaml

spring:# datasource 数据源配置内容datasource:url: jdbc:mysql://127.0.0.1:3306/test-user?useSSL=false&useUnicode=true&characterEncoding=UTF-8driver-class-name: com.mysql.jdbc.Driverusername: rootpassword: root1234

三、功能详解

1.自增主键

CREATE TABLE auto_increment (id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',name VARCHAR(100) NOT NULL COMMENT '名称',create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) COMMENT='主键自增表';

表单说明:在数据库软件如navicat中直接插入数据时,数据呈现主键自增情况,但使用mybatis-plus直接插入数据则不会。
(1)直接为实体id字段添加注解@TableId(type = IdType.AUTO),加上此注解后插入的数据就可以实现主键自增了。
实体类如下:

@TableName(value = "auto_increment")
@Data
public class AutoIncrementDO {@TableId(type = IdType.AUTO)private Long id;private String name;private LocalDateTime createTime;
}

(2)全局配置,在配置文件中加入以下配置

mybatis-plus:global-config:db-config:id-type: auto # 全局主键策略

实体类如下:

@TableName(value = "auto_increment")
@Data
public class AutoIncrementDO {// 字段名id时会自动识别为主键,否则需要加上 @TableId 注解private Long id;private String name;private LocalDateTime createTime;
}

ps:数据库主键必须设置为自增,否则会报错

2.逻辑删除

CREATE TABLE logic_delete (id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',name VARCHAR(50) NOT NULL COMMENT '名称',create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',deleted BIT NOT NULL DEFAULT FALSE COMMENT '是否删除'
) COMMENT='逻辑删除表';

表单说明:deleted字段默认设为false即0,删除数据时值需要将deleted字段置为1即可,不需要真正的删除数据。

mybatis-plus如何实现这一需求呢?
(1)直接在表示逻辑删除的字段上添加注解@TableLogic即可,默认值为0,删除值为1,若想反过来需要自定义@TableLogic(value = "1", delval = "0")或者@TableLogic(value = "false", delval = "true")
(2)全局配置:表示删除的字段上添加注解@TableLogic,全局配置默认值和删除值,配置如下。

mybatis-plus:global-config:db-config:logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)logic-delete-value: 1 # 逻辑已删除值(默认为 1)

ps:若字段上的注解不仅仅为@TableLogic,而是例如@TableLogic(value = "1", delval = "0")等情况,那么该表的逻辑删除按该注解来,即该表0表示删除

3.操作时间自动填充

CREATE TABLE auto_update_time (id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键',content VARCHAR(255) NOT NULL COMMENT '名称',create_time TIMESTAMP DEFAULT NULL COMMENT '创建时间',update_time TIMESTAMP DEFAULT NULL COMMENT '更新时间'
)COMMENT='时间自动更新表';

表单说明:为不产生影响,数据库中创建时间与更新时间不设置默认值,也不自动更新。

mybatis-plus实现操作时间自动填充以及更新步骤如下:
①字段上添加如下注解:

@Data
@TableName("auto_update_time")
public class AutoUpdateTimeDO {@TableId(type = IdType.AUTO)private Long id;private String content;@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;
}

②实现 MetaObjectHandler 接口:

@Component
public class DefaultDBFieldHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {setInsertFieldValByName("createTime", LocalDateTime.now(), metaObject);setInsertFieldValByName("updateTime", LocalDateTime.now(), metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {setUpdateFieldValByName("updateTime", LocalDateTime.now(), metaObject);}
}

4.其他字段自动填充

如创建人与更新人自动填充,这里会和创建时间以及更新时间自动填充一起,二者实现都需要实现MetaObjectHandler接口。
实现如下:
①字段上添加如下注解:

@Data
@TableName(value = "auto_fill_operator")
public class AutoFillOperatorDO extends BaseDO{@TableId(type = IdType.AUTO)private Long id;private String content;
}
@Data
public class BaseDO {@TableField(fill = FieldFill.INSERT)private String creator;@TableField(fill = FieldFill.INSERT_UPDATE)private String updater;@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;
}

②实现 MetaObjectHandler 接口:

@Component
public class DefaultDBFieldHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {if (metaObject.getOriginalObject() instanceof BaseDO) {BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();LocalDateTime current = LocalDateTime.now();// 创建时间为空,则填充当前时间if (Objects.isNull(baseDO.getCreateTime())) {baseDO.setCreateTime(current);}// 更新时间为空,则填充当前时间if (Objects.isNull(baseDO.getUpdateTime())) {baseDO.setUpdateTime(current);}String user = "creator";// 创建人为空,则填充当前用户if (Objects.isNull(baseDO.getCreator())) {baseDO.setCreator(user);}// 更新人为空,则填充当前用户if (Objects.isNull(baseDO.getUpdater())) {baseDO.setUpdater(user);}}}@Overridepublic void updateFill(MetaObject metaObject) {// 更新时间为空,则以当前时间为更新时间Object modifyTime = getFieldValByName("updateTime", metaObject);if (Objects.isNull(modifyTime)) {setFieldValByName("updateTime", LocalDateTime.now(), metaObject);}// 当前登录用户不为空,更新人为空,则当前登录用户为更新人Object modifier = getFieldValByName("updater", metaObject);String user = "updater";if (Objects.isNull(modifier)) {setFieldValByName("updater", user, metaObject);}}
}

5.分页查询

@Mapper
public interface CrudBaseMaoper extends BaseMapper<CrudBaseDO> {
}
@Service
public class CrudBaseServiceImpl {@Resourceprivate CrudBaseMaoper crudBaseMaoper;public IPage<CrudBaseDO> page(String name) {// 构造分页参数Page<CrudBaseDO> page = new Page<>(1, 10); // 当前页, 每页显示条数QueryWrapper<CrudBaseDO> queryWrapper = new QueryWrapper<>();queryWrapper.lambda().like(CrudBaseDO::getCompanyName, name);return crudBaseMaoper.selectPage(page, queryWrapper);}

分页查询total为0,需要配置分页插件,如下:

@Configuration
public class MybatisPlusConfig {// 分页查询拦截器,可以获取total值@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 根据数据库类型选择return interceptor;}
}

6.自定义动态查询

场景:在数据库查询中,经常遇到需要根据多个可选字段进行动态查询的情况。传统写法需要为每个字段编写判空逻辑,代码冗长且重复。
通过自定义 LambdaQueryWrapper 扩展方法,实现简洁的动态查询:
示例:

public class LambdaQueryWrapperX<T> extends LambdaQueryWrapper<T> {public LambdaQueryWrapperX<T> likeIfPresent(SFunction<T, ?> column, String val) {if (StringUtils.hasText(val)) {return (LambdaQueryWrapperX<T>) super.like(column, val);}return this;}
}
@Mapper
public interface CrudProMapper extends BaseMapper<CrudProDO> {
}
@Service
public class CrudProServiceImpl implements CrudProService {@Resourceprivate CrudProMapper crudProMapper;@Overridepublic IPage<CrudProDO> getCrudProPage(CrudProPageReqVO reqVO) {IPage<CrudProDO> page = new Page<>(1, 10);return crudProMapper.selectPage(page, new LambdaQueryWrapperX<CrudProDO>().likeIfPresent(CrudProDO::getCompanyName, reqVO.getCompanyName()).likeIfPresent(CrudProDO::getCompanyCode, reqVO.getCompanyCode()));}
}

其他方法也可以一样的实现,比如eqIfPresent

7.代码生成器

(1)相关依赖

 <!-- 实现对 MyBatis Plus 的自动化配置 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version></dependency><!-- 代码自动生成器--><!-- 与mybatis-plus版本保持一致--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.3.1</version></dependency><!-- 模板引擎依赖,默认使用 Velocity --><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.3</version></dependency><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId></dependency>

(2)生成器代码

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;import java.util.Collections;public class CodeGenerator {public static void main(String[] args) {// 多模块地址前缀,没有可不写String prefixPath = "/kaishu-sql-crud/kaishu-sql-crud-mybatis-plus-pro/";FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/test-user?useSSL=false&useUnicode=true&characterEncoding=UTF-8","root","root1234").globalConfig(builder -> {builder.author("kaishu")       // 设置作者.outputDir(System.getProperty("user.dir") + prefixPath + "/src/main/java") // 输出目录.enableSwagger()        // 开启swagger.fileOverride();        // 覆盖已生成文件}).packageConfig(builder -> {builder.parent("org.kaishu.sql.crud.mybatis.plus.pro")    // 设置父包名.moduleName("generatordemo")     // 设置父包模块名.pathInfo(Collections.singletonMap(OutputFile.xml,System.getProperty("user.dir") + prefixPath + "/src/main/resources/mapper")); // 设置mapperXml路径}).strategyConfig(builder -> {builder.addInclude("t_auto_genarater", "t_test_auto_genarater") // 设置需要生成的表名.addTablePrefix("t_", "t_") // 设置过滤表前缀.entityBuilder()         // 实体类配置.enableLombok()         // 启用Lombok.controllerBuilder()    // Controller配置.enableRestStyle()      // 启用@RestController.mapperBuilder()        // Mapper配置.enableMapperAnnotation(); // 启用@Mapper}).templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎.execute();}
}

更详细的配置参考如下:
(1)实体类生成配置

.strategyConfig(builder -> {builder.entityBuilder().enableLombok() // 使用Lombok.enableChainModel() // 链式模型.enableRemoveIsPrefix() // 移除is前缀.enableTableFieldAnnotation() // 字段注解.versionColumnName("version") // 乐观锁字段名.logicDeleteColumnName("deleted") // 逻辑删除字段名.naming(NamingStrategy.underline_to_camel) // 命名策略.columnNaming(NamingStrategy.underline_to_camel).addSuperEntityColumns("id", "create_time", "update_time") // 公共字段.formatFileName("%sEntity") // 文件名称格式.addIgnoreColumns("is_deleted"); // 忽略字段
})

(2)Mapper生成配置

.strategyConfig(builder -> {builder.mapperBuilder().enableBaseResultMap() // 生成resultMap.enableBaseColumnList() // 生成columnList.enableMapperAnnotation() // @Mapper注解.formatMapperFileName("%sDao") // Mapper文件命名.formatXmlFileName("%sXml"); // Xml文件命名
})

(3)Service生成配置

.strategyConfig(builder -> {builder.serviceBuilder().formatServiceFileName("%sService") // Service接口命名.formatServiceImplFileName("%sServiceImpl"); // Service实现类命名
})

(4)Controller生成配置

.strategyConfig(builder -> {builder.controllerBuilder().enableRestStyle() // 使用@RestController.enableHyphenStyle() // 使用驼峰转连字符.formatFileName("%sController") // 文件命名.enableFileOverride(); // 覆盖已生成文件
})

8.代码生成器(自定义模板)

示例:这里只自定义实体类生成模板,其余照旧,这里我需要让实体类都继承我已定义好的的类BaseDO

(1)依赖同上
(2)生成器代码,基本同上

.strategyConfig(builder -> {...
})
// 加上这行代码即可
.templateConfig(builder -> {builder.entity("/templates/custom-entity.java");})

(2)自定义实体模板文件,在\src\main\resources\templates\目录下新建custom-entity.java.ftl文件,文件内容如下

package ${package.Entity};<#-- 基础导入 -->
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import lombok.EqualsAndHashCode;
<#-- 导入项目基础类 -->
import org.kaishu.sql.crud.mybatis.plus.pro.dal.dataobject.BaseDO;<#-- 类注释 -->
/**
* ${table.comment!} 实体类
*
* @author ${author}
* @since ${date}
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("${table.name}")
public class ${entity} extends BaseDO {private static final long serialVersionUID = 1L;<#-- 生成字段(自动排除BaseDO中已存在的字段) -->
<#list table.fields as field><#if !['id','create_time','update_time','creator','updater','deleted']?seq_contains(field.name)>/*** ${field.comment!}*/@TableField("${field.name}")private ${field.propertyType} ${field.propertyName};</#if>
</#list>
}

·

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

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

相关文章

docker compose 启动指定的 service

使用 Docker Compose 启动指定服务 要在 Docker Compose 中启动特定的服务而不是所有服务&#xff0c;可以使用以下命令&#xff1a; docker compose up [服务名] 基本用法 启动单个服务&#xff1a; docker compose up service_name 启动多个指定服务&#xff1a; docker …

wordcount程序

### 在 IntelliJ IDEA 中编写和运行 Spark WordCount 程序 要使用 IntelliJ IDEA 编写并运行 Spark 的 WordCount 程序&#xff0c;需按照以下流程逐步完成环境配置、代码编写以及任务提交。 --- #### 1. **安装与配置 IntelliJ IDEA** 确保已正确安装 IntelliJ IDEA&#x…

SmartETL函数式组件的设计与应用

SmartETL框架主要采用了面向对象的设计思想&#xff0c;将ETL过程中的处理逻辑抽象为Loader和Processor&#xff08;对应loader模块和iterator模块&#xff09;&#xff0c;所有流程组件需要继承或实现DataProvider&#xff08;iter方法&#xff09;或JsonIterator&#xff08;…

鸿蒙AI开发:10-多模态大模型与原子化服务的集成

鸿蒙AI开发&#xff1a;10-多模态大模型与原子化服务的集成 在鸿蒙生态中&#xff0c;多模态大模型与原子化服务的集成是一个重要课题。本文将介绍如何在鸿蒙平台上进行多模态大模型与原子化服务的集成&#xff0c;以及相关的技术细节和实际案例。 鸿蒙AI开发概述 什么是鸿蒙AI…

python打卡day29@浙大疏锦行

知识点回顾 类的装饰器装饰器思想的进一步理解&#xff1a;外部修改、动态类方法的定义&#xff1a;内部定义和外部定义 作业&#xff1a;复习类和函数的知识点&#xff0c;写下自己过去29天的学习心得&#xff0c;如对函数和类的理解&#xff0c;对python这门工具的理解等&…

20250516使用TF卡将NanoPi NEO core开发板出厂的Ubuntu core22.04.3系统降级到Ubuntu core16.04.2

20250516使用TF卡将NanoPi NEO core开发板出厂的Ubuntu core22.04.3系统降级到Ubuntu core16.04.2 2025/5/16 10:58 缘起&#xff1a;NanoPi NEO core核心板出厂预制的OS操作系统为Ubuntu core22.04.3系统。 【虽然是友善之臂提供的最新的系统&#xff0c;但是缺少很多用用程序…

密西根大学新作——LightEMMA:自动驾驶中轻量级端到端多模态模型

导读 目前将自动驾驶与视觉语言模型&#xff08;VLMs&#xff09;结合的研究越来越火热&#xff0c;VLMs已经证明了其对自动驾驶的重要作用。本文引入了一种用于自动驾驶的轻量级端到端多模态模型LightEMMA&#xff0c;它能够集成和评估当前的商业和开源模型&#xff0c;以研究…

框架之下再看HTTP请求对接后端method

在当今的软件开发领域&#xff0c;各类框架涌现&#xff0c;极大地提升了开发效率。以 Java 开发为例&#xff0c;Spring 框架不断演进&#xff0c;Spring Boot 更是简化到只需引入 Maven 包&#xff0c;添加诸如SpringBootApplication、RestController等注解&#xff0c;就能轻…

Vue+Go 自定义打字素材的打字网站

Typing_Key_Board 这是一个基于Vue 3和Go语言的自定义素材打字练习网站&#xff0c;灵感来源于常用字打字练习&#xff0c;解决了大多数网站无法自定义打字素材的问题。在 Typing_Key_Board (简称TKB)中&#xff0c;用户可以自定义打字素材进行练习&#xff0c;在复习代码的同…

开源物联网平台(OpenRemote)

在物联网技术蓬勃发展的当下&#xff0c;OpenRemote作为一款强大的开源物联网平台&#xff0c;正逐渐在多个领域崭露头角。尤其是在智能能源管理领域&#xff0c;它为微电网和分布式能源网络提供了全面且灵活的数据集成与管理方案&#xff0c;展现出独特的优势。 OpenRemote提供…

Spring Security与SaToken的对比与优缺点分析

Spring Security与SaToken对比分析 一、框架定位 Spring Security 企业级安全解决方案&#xff0c;深度集成Spring生态提供完整的安全控制链&#xff08;认证、授权、会话管理、攻击防护&#xff09;适合中大型分布式系统 SaToken 轻量级权限认证框架&#xff0c;专注Token会…

每日一道leetcode(新学数据结构版)

208. 实现 Trie (前缀树) - 力扣&#xff08;LeetCode&#xff09; 题目 Trie&#xff08;发音类似 "try"&#xff09;或者说 前缀树 是一种树形数据结构&#xff0c;用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景&#xff0c;例如自动…

【自然语言处理与大模型】大模型(LLM)基础知识④

&#xff08;1&#xff09;微调主要用来干什么&#xff1f; 微调目前最主要用在定制模型的自我认知和改变模型对话风格。模型能力的适配与强化只是辅助。 定制模型的自我认知&#xff1a;通过微调可以调整模型对自我身份、角色功能的重新认知&#xff0c;使其回答更加符合自定义…

基于 Spring Boot 瑞吉外卖系统开发(十五)

基于 Spring Boot 瑞吉外卖系统开发&#xff08;十五&#xff09; 前台用户登录 在登录页面输入验证码&#xff0c;单击“登录”按钮&#xff0c;页面会携带输入的手机号和验证码向“/user/login”发起请求。 定义UserMapper接口 Mapper public interface UserMapper exte…

什么是TCP协议?它存在哪些安全挑战?

一、TCP协议概述 TCP&#xff08;传输控制协议&#xff09;是互联网中面向连接、可靠的传输层协议&#xff0c;主要负责在不可靠的IP层上实现数据的可靠传输。其核心特点包括&#xff1a; 面向连接&#xff1a;通信前需通过三次握手&#xff08;SYN-SYN/ACK-ACK&#xff09;建…

12条热门照片提示

12条热门照片提示 1. 赛博朋克光彩 (Cyberpunk Glow-Up) 未在文件中显示2. 卡通化我 (Cartoonify Me) Convert this image of [your subject here] into a 3D Pixar-style cartoon clean lines, soft lighting, expressive features, and a polished render that feels cine…

Java求职面试揭秘:从Spring到微服务的技术挑战

文章简述 在这篇文章中&#xff0c;我们将通过一个幽默的面试场景&#xff0c;揭秘互联网大厂Java求职者在面试中面对的技术挑战。面试官将从Spring框架、微服务架构到大数据处理等多个维度进行提问&#xff0c;并详细讲解这些技术点的应用场景和解决方案&#xff0c;帮助小白…

用Python输出一个文件夹的所有文件结构

输出一个文件夹的所有目录和文件结构 新建一个Python文件&#xff0c;输入 这个文件表示查询一个文件夹所有的目录结构 import osdef print_directory_structure(root_dir):"""打印树状目录结构&#xff08;优化版&#xff09;"""if not os.p…

R语言的专业网站top5推荐

李升伟 以下是学习R语言的五个顶级专业网站推荐&#xff0c;涵盖教程、社区、资源库和最新动态&#xff1a; 1.R项目官网 (r-project.org) R语言的官方网站&#xff0c;提供软件下载、文档、手册和常见问题解答。特别适合初学者和高级用户&#xff0c;是获取R语言核心资源的…

IntelliJ IDEA给Controller、Service、Mapper不同文件设置不同的文件头注释模板、Velocity模板引擎

通过在 IntelliJ IDEA 中的 “Includes” 部分添加多个文件头模板&#xff0c;并在 “Files” 模板中利用这些包含来实现不同类型文件的注释。以下是为 Controller、Service、Mapper 文件设置不同文件头的完整示例&#xff1a; 1. 设置 Includes 文件头模板 File > Settin…