这篇MyBatisPlus文章是基于 狂神说视频的笔记总结,仅供个人学习和复习用。强烈推荐前往学习狂神教程。
MyBatisPlus概述
简介
MyBatis-Plus是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发提高效率而生
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
快速入门
1.创建数据库MyBatis_Plus
2.创建user表
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
DELETE FROM user;
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
3.创建Spring-boot项目,导入依赖
pom
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--MyBatis-Plus 注意:不能和mybatis同时存在,否则会导致冲突-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
4.编写配置类连接数据库
application.yaml
spring:
datasource:
username: root
password: 123455
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSl=false
5.编码
pojo
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
mapper接口
//在对应的mapper上面继承基本的类 BaseMapper
@Repository //代表持久层
public interface UserMapper extends BaseMapper<User> {
}
在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:
@SpringBootApplication
@MapperScan("com.mybatisplus.mapper")
public class MybatisplusStudyApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisplusStudyApplication.class, args);
}
}
测试类中测试
@SpringBootTest
class MybatisplusStudyApplicationTests {
@Autowired
UserMapper userMapper;
@Test
void contextLoads() {
//参数是一个Wapper,条件构造器,这里我们先不用
//查询全部用户
List<User> users = userMapper.selectList(null);
for (User user : users) {
System.out.println(user.toString());
}
}
}
结果
User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)
主键自增
一般来说MyBatisPlus是帮我们默认设置id为雪花算法,及会帮我们自动填充id。
如需设置id自增
1.数据库需要设置id为自增
2.实体类id属性添加注解
@TableId(type = IdType.AUTO)
private Integer id;
配置日志
配置日志方便查看sql语句
# 配置日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
自动填充
应用场景
比如:在数据库中我们有两个字段,gmt_create和gmt_modified分别存放创建数据的时间和修改数据的时间。为了不去改动数据库表,我们可以通过代码自动填充数据。
使用
1.实体类配置注解 @TableField
User
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
//自动填充内容
@TableField(fill = FieldFill.INSERT )
private LocalDateTime gmtCreate;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime gmtModified;
}
2.编写自定义实现类
MyMetaObjectHandler
package com.mybatisplus.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Slf4j
@Component //注意需要添加到ioc容器中
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert ");
this.strictInsertFill(metaObject,"gmtCreate", LocalDateTime.class,LocalDateTime.now());
this.strictInsertFill(metaObject,"gmtModified", LocalDateTime.class,LocalDateTime.now());
}
//更新时的填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update");
this.strictUpdateFill(metaObject,"gmtModified",LocalDateTime.class,LocalDateTime.now());
}
}
注意事项:
填充原理是直接给entity的属性设置值!!!
注解则是指定该属性在对应情况下必有值,如果无值则入库会是null
MetaObjectHandler提供的默认方法的策略均为:如果属性有值则不覆盖,如果填充值为null则不填充
字段必须声明TableField注解,属性fill选择对应策略,该声明告知Mybatis-Plus需要预留注入SQL字段
填充处理器MyMetaObjectHandler在 Spring Boot 中需要声明@Component或@Bean注入
要想根据注解FieldFill.xxx和字段名以及字段类型来区分必须使用父类的strictInsertFill或者strictUpdateFill方法
不需要根据任何来区分可以使用父类的fillStrategy方法
3.测试
@Test
public void testInsert(){
User user = new User();
user.setName("zskyz");
user.setAge(6);
user.setEmail("55******13@qq.com");
int insert = userMapper.insert(user);
System.out.println(insert);
}
@Test
public void TestUpdate(){
User user = new User();
//MyBatis-Plus通过条件自动拼接sql
user.setId(1L);
user.setName("zsssssssssss");
user.setAge(55);
int i = userMapper.updateById(user);
System.out.println(i);
}
乐观锁
乐观锁 : 故名思意十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题,再次更新值测试
悲观锁:故名思意十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
乐观锁:1、先查询,获得版本号 version = 1
-- A
update user set name = "kuangshen", version = version + 1
where id = 2 and version = 1
-- B 线程抢先完成,这个时候 version = 2,会导致 A 修改失败!
update user set name = "kuangshen", version = version + 1
where id = 2 and version = 1
使用
1.数据库添加version字段
2.实体类添加字段跟@Version注解
@Version//乐观锁Version注解
private Integer version;
注意在旧版本中需要添加一个config类
@Configuration
public class MybatisConfig {
// 注册乐观锁插件(旧版:3.0.5)
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}
3.测试
//测试乐观锁
@Test
public void Testlock(){
//1.查询用户信息
User user = userMapper.selectById(1L);
//2.修改用户信息
user.setName("张三");
user.setAge(11);
user.setEmail("123456798@qq.com");
//3.执行更新操作
userMapper.updateById(user);
}
说明:
- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下 newVersion = oldVersion + 1
- newVersion 会回写到 entity 中
- 仅支持 updateById(id) 与 update(entity, wrapper) 方法
- 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
分页
1.添加配置类
MybatisConfig
@Configuration
public class MybatisConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
}
2.测试
//分页查询
@Test
public void Test1(){
Page<User> page = new Page<>(1,3);//参数1,表示当前页,参数2.页面大小
userMapper.selectPage(page,null);
page.getRecords().forEach(System.out::println);//控制台显示数据
}
逻辑删除
物理删除 :从数据库中直接移除.
逻辑删除 :在数据库中没有被移除,而是通过一个变量来让他失效!deleted = 0 => deleted = 1
1.数据库添加deleted字段
2.添加实体类属性和注解
@TableLogic//逻辑删除
private Integer deleted;
注意新版的无需配置MybatisConfig
3.添加配置 yaml
application.yaml
mybatis-plus:
global-config:
db-config:
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
4.测试
//逻辑删除
@Test
public void TestDelete(){
userMapper.deleteById(1L);
}
代码自动生成器
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
1.添加依赖 mybatis-plus-generator
因为有默认模板引擎所以需要添加依赖velocity-engine-core,可以参考官方文档去更改模板引擎。
pom
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--MyBatis-Plus 注意:不能和mybatis同时存在,否则会导致冲突-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!--MyBatisPlus代码生成器依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!--默认的模板引擎依赖 可改参考MyBatisPlus官方文档-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<!--日志门面 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.1</version>
</dependency>
2.编写配置文件
application.yaml
#服务端口
server:
port: 90000
# 禁用缓存模板
# 连接数据库
spring:
thymeleaf:
cache: false
profiles:
active: "dev"
datasource:
username: "root"
password: *****
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSl=false
mybatis-plus:
global-config:
db-config:
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
3.编写配置类
SwaggerConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
@Configuration
@EnableSwagger2 //开启Swagger2
public class SwaggerConfig {
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
//RequestHandlerSelectors 配置要扫描接口的方式
//basePackage 指定要扫描的包
//any() 扫描全部
//none() 不扫描
.apis(RequestHandlerSelectors.basePackage("com.zsky.包名.controller"))
//paths() 过滤,只扫描指定路径controller中 @RequestMapping("/zz/hello")
//.paths(PathSelectors.ant("/zz/hello"))
.build();
}
private ApiInfo apiInfo(){
final Contact DEFAULT_CONTACT = new Contact("zsky", "https://www.baidu.com", "5*****13@qq.com");
return new ApiInfo(
"zsky-swagger",
"我希望每天叫醒我的不是闹钟,是梦想。",
"v1.0",
"https://fanyi.baidu.com/translate?aldtype=16047&query=xpected+1+arguments+but+found+0&keyfrom=baidu&smartresult=dict&lang=auto2zh#en/zh/term",
DEFAULT_CONTACT,
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0",
new ArrayList());
}
}
MyBatisPlusConfig
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {
//分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
//乐观锁组件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}
4.执行代码生成器
CodeProvide
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
// 代码自动生成器
public class CodeProvider {
public static void main(String[] args) {
// 需要构建一个 代码自动生成器 对象
AutoGenerator mpg = new AutoGenerator();
// 配置策略
// 1、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");//获取当前项目目录
gc.setOutputDir(projectPath+"/src/main/java");//输出的项目路径
gc.setAuthor("zskyz233333");//设置作者
gc.setOpen(false);//不打开资源管理器
gc.setFileOverride(false); // 是否覆盖
gc.setServiceName("%sService"); // 去Service的I前缀
gc.setIdType(IdType.ASSIGN_ID);//设置默认id算法
gc.setDateType(DateType.ONLY_DATE);//设置日期类型
gc.setSwagger2(true);//开启Swagger2
mpg.setGlobalConfig(gc);
//2、设置数据源
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSl=false");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("******");
dsc.setDbType(DbType.MYSQL);//设置数据库类型为MySql
mpg.setDataSource(dsc);
//3、包的配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("study");//生成模块名,可以去掉
pc.setParent("com.zsky");//输出包下
pc.setEntity("entity");//对应包名
pc.setMapper("mapper");
pc.setService("service");
pc.setController("controller");
mpg.setPackageInfo(pc);
//4、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("user"); // 设置要映射的表名可多个
strategy.setNaming(NamingStrategy.underline_to_camel);//设置包命名规则,下划线转驼峰命名
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//设置列命名规则,下划线转驼峰命名
strategy.setEntityLombokModel(true); // 自动lombok;
strategy.setLogicDeleteFieldName("deleted");//设置逻辑删除
// 自动填充配置
TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);
ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(gmtCreate);
tableFills.add(gmtModified);
strategy.setTableFillList(tableFills);
// 乐观锁
strategy.setVersionFieldName("version");
strategy.setRestControllerStyle(true);
strategy.setControllerMappingHyphenStyle(true); //localhost:8080/hello_id_2
mpg.setStrategy(strategy);
mpg.execute(); //执行
}
}