【MyBatis Plus】从入门到精通带你领悟MyBatis-Plus
🎉🎉欢迎来到我的CSDN主页!🎉🎉
🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚
🌟推荐给大家我的专栏《MyBatis-Plus》。🎯🎯
👉点击这里,就可以查看我的主页啦!👇👇
🎁如果感觉还不错的话请给我点赞吧!🎁🎁
💖期待你的加入,一起学习,一起进步!💖💖
一、MyBatis-Plus简介
1.什么是MyBatis-Plus
MyBatis-Plus?(opens new window)(简称 MP)是一个?MyBatis?(opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
愿景
我们的愿景是成为 MyBatis 最好的搭档,就像?魂斗罗?中的 1P、2P,基友搭配,效率翻倍。
2.MyBatis-Plus的特点
2.1.特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
2.2.支持数据库
任何能使用?
MyBatis
?进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下,如果不在下列表查看分页部分教程 PR 您的支持。
-
MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb,informix,TDengine,redshift
-
达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库,优炫数据库,星瑞格数据库
2.3.框架结构
二、入门MyBatis-Plus
1.添加依赖
使用Spring Initializer快速初始化一个 Spring Boot 工程(工程将以 MySQL 作为默认数据库)
基于Spring Boot 2.7.12和MyBatis-Plus 3.5.2配置项目依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
2.MyBatis-Plus文件配置
application.yml配置文件
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 1234
url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&useSSL=false
mybatis-plus:
# Mybatis Mapper所对应的XML位置
mapper-locations: classpath:mapper/*.xml
# 别名包扫描路径
type-aliases-package: com.csdn.boot.pojo
# 是否开启自动驼峰命名规则(camel case)映射
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.zking.spbootmp.mapper: debug
在 Spring Boot 启动类中添加 @MapperScan
注解,扫描 Mapper 文件夹: ?
@SpringBootApplication
@MapperScan("com.csdn.boot.mapper")
public class BootApplication {
public static void main(String[] args) {
SpringApplication.run(BootApplication.class, args);
}
}
3.代码生成
可以使用官方提供的代码生成类,但是我觉得不符合个人需求,所以我自己写了一个
?MySQLGenerator.java
package com.csdn.boot;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@Slf4j
public class MySQLGenerator {
private final static String URL = "jdbc:mysql://localhost:3306/bookshop";
private final static String USERNAME = "root";
private final static String PASSWORD = "root123";
private final static DataSourceConfig.Builder DATA_SOURCE_CONFIG =
new DataSourceConfig.Builder(URL, USERNAME, PASSWORD);
public static void main(String[] args) {
FastAutoGenerator.create(DATA_SOURCE_CONFIG)
.globalConfig(
(scanner, builder) ->
builder.author(scanner.apply("请输入作者名称?"))
.outputDir(System.getProperty("user.dir") + "\\src\\main\\java")
.commentDate("yyyy-MM-dd")
.dateType(DateType.TIME_PACK)
)
.packageConfig((builder) ->
builder.parent("com.zking.boot")
.entity("pojo")
.service("service")
.serviceImpl("service.impl")
.mapper("mapper")
.xml("mapper.xml")
.pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "\\src\\main\\resources\\mapper"))
)
.injectionConfig((builder) ->
builder.beforeOutputFile(
(a, b) -> log.warn("tableInfo: " + a.getEntityName())
)
)
.strategyConfig((scanner, builder) ->
builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
.addTablePrefix("tb_", "t_", "lay_", "meeting_", "sys_")
.entityBuilder()
.enableChainModel()
.enableLombok()
.enableTableFieldAnnotation()
.controllerBuilder()
.enableRestStyle()
.enableHyphenStyle()
.build()
)
.templateEngine(new FreemarkerTemplateEngine())
.execute();
}
protected static List<String> getTables(String tables) {
return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
}
}
根据自己的实际情况调试即可,然后运行该文件
4.根据生成代码完成CURD
注意需要在mapper类上加上注解@Repository否则报错!!
4.1.查看
@RestController
@RequestMapping("/BOOK")
public class BookController {
@Autowired
private IBookService bookService;
@RequestMapping("/list")
public Object list(){
return bookService.list();
}
}
这里我用测试工具测试一下
4.2.新增
新增之前先讲一下@TableId主键注解,放置于实体类中的主键字段上。
package com.csdn.boot.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
/**
* <p>
* 书本信息表
* </p>
*
* @author JAVA方文山
* @since 2023-12-16
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("t_book")
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 书本编号
*/
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 书本名称
*/
@TableField("bookname")
private String bookname;
/**
* 书本价格
*/
@TableField("price")
private Float price;
/**
* 书本类型
*/
@TableField("booktype")
private String booktype;
}
-
@TableId注解属性
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 主键字段名 |
type | Enum | 否 | IdType.NONE | 指定主键类型 |
@TableId注解type属性IdType
主键生成策略介绍:
值 | 描述 |
---|---|
AUTO | 数据库 ID 自增 |
NONE | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) |
INPUT | insert 前自行 set 主键值 |
ASSIGN_ID | 分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator 的方法nextId (默认实现类为DefaultIdentifierGenerator 雪花算法) |
ASSIGN_UUID | 分配 UUID,主键类型为 String(since 3.3.0),使用接口IdentifierGenerator 的方法nextUUID (默认 default 方法) |
我们这里使用一下ASSIGN_ID?
@RequestMapping("/save")
public Object save(Book book){
return bookService.save(book);
}
可以看到ID就变成了雪花ID
4.3.修改
@TableField字段注解(非主键),其中fill字段自动填充策略,具体策略如下:
值 | 描述 |
---|---|
DEFAULT | 默认不处理 |
INSERT | 插入时填充字段 |
UPDATE | 更新时填充字段 |
INSERT_UPDATE | 插入和更新时填充字段 |
注解则是指定该属性在对应情况下必有值,如果无值则入库会是null
。
-
自定义实现类 MyMetaObjectHandler
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
?
? ?@Override
? ?public void insertFill(MetaObject metaObject) {
? ? ? ?log.info("开始新增操作自动填充 ....");
? ? ? ?this.strictInsertFill(metaObject, "createdate", LocalDateTime.class, LocalDateTime.now());
? }
?
? ?@Override
? ?public void updateFill(MetaObject metaObject) {
? ? ? ?log.info("开始更新操作自动填充 ....");
? ? ? ?this.strictUpdateFill(metaObject, "createdate", LocalDateTime.class, LocalDateTime.now());
? }
}
情况一:fill = FieldFill.DEFAULT,无论是新增和更新都不进行自动填充;
情况二:fill = FieldFill.INSERT,执行新增操作自动填充数据;
情况三:fill = FieldFill.UPDATE,执行更新操作,若字段不为空则自动填充数据;再次执行更新操作不会刷新数据。
我这里就对价格做处理
@RequestMapping("/update")
public Object update(Book book){
return bookService.updateById(book);
}
可以看到这里没有带price,那么它就会采用自动填充策略
4.4.删除
@RequestMapping("/del")
public Object del(Book book){
return bookService.removeById(book);
}
删除就直接删除了没什么好说的
到这里我的分享就结束了,欢迎到评论区探讨交流!!
💖如果觉得有用的话还请点个赞吧 💖
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!