文章目录
Mybatis-Plus
1.什么是Mybatis-Plus
官网:https://baomidou.com/guide/
- 可以节省我们开发时间,因为他可以自动完成大量的CRUD代码;
- 在 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
2.快速开始
创建数据库表:
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) ); 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');创建一个空的 Spring Boot 工程
导入依赖
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> </dependency>连接数据库
#连接数据库 spring.datasource.password=root spring.datasource.username=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/user?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8以前(entity-mapper(mapper.xml)-service-controller)
现在就简化可配置mapper.xml文件了;在mapper接口处继承BaseMapper
注意:需要在主启动类添加mapperscan注解,扫描mapper文件夹(@MapperScan(“com.simon.mapper”)//扫描mapper文件夹)
编写实体类User
package com.simon.entity; import lombok.Data; @Data public class User { private Long id; private String name; private Integer age; private String email; }- 编写mapper接口
package com.simon.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.simon.entity.User; import org.springframework.stereotype.Repository; @Repository//代表持久层 //继承一个基础类,至此所有的crud操作就已经编写完成了 public interface UserMapper extends BaseMapper<User> { //可以编写一些自己的方法,但是其父类有很多方法可以直接使用 }至此就可以直接编写测试类进行CRUD操作了。
@SpringBootTest class MybatisPlusApplicationTests { @Resource private UserMapper userMapper; /* * 现在所有的方法都是父类的方法,也可以自己编写一些没有的方法 * */ @Test public void contextLoads() { //Wrapper是一个条件构造器,不需要就直接为null List<User> users = userMapper.selectList(null); users.forEach(System.out::println); } } /* 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) */
3. 配置日志
#配置日志
#默认的控制台输出,使用log4j需要导入对应的依赖
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

CRUD
1. 插入数据(insert)
@Test
public void contextLoads1() {
//测试插入数据
// User user = new User("simon",22,"1092523696@qq.com");
User user = new User();
user.setName("simon");
user.setAge(22);
user.setEmail("1092523696@qq.com");
int insert = userMapper.insert(user);
System.out.println(insert);
System.out.println(user);
//==> Preparing: INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
//==> Parameters: 1333586687944278018(Long), simon(String), 22(Integer), 1092523696@qq.com(String)
id主键生成策略
- uuid
- 自增id
- 雪花算法
需要在实体类主键id上添加注解
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 数据库ID自增
* <p>该类型请确保数据库设置了 ID自增 否则无效</p>
*/
AUTO(0),
/**
* 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
*/
NONE(1),
/**
* 用户输入ID
* <p>该类型可以通过自己注册自动填充插件进行填充</p>
*/
INPUT(2),
/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
/**
* 分配ID (主键类型为number或string),
* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法)
*
* @since 3.3.0
*/
ASSIGN_ID(3),
/**
* 分配UUID (主键类型为 string)
* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-",""))
*/
ASSIGN_UUID(4),
2. 更新数据(update)
@Test
public void contextLoads2() {
//测试插入数据
// User user = new User("simon",22,"1092523696@qq.com");
User user = new User();
user.setAge(30);
user.setId(2L);
int i = userMapper.updateById(user);
/*
* ==> Preparing: UPDATE user SET age=? WHERE id=?
==> Parameters: 30(Integer), 2(Long)
<== Updates: 1
* */
}
3. 自动填充(时间)
- 所有的数据表都应该包含创建时间和修改时间(create_time、modify_time),且这应该被自动的生成。
先在数据库中添加字段create_time、modify_time;
实体类对应属性
private Date createTime; private Date updateTime;需要在实体类属性上添加注解
@TableField(fill = FieldFill.INSERT)//在插入的时候自动添加 private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE)//在插入和修改的时候均添加 private Date updateTime;需要编写处理器处理该注解
package com.simon.handlers; 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.util.Date; @Component @Slf4j public class MyMetaObjectHandler implements MetaObjectHandler { @Override //插入时的填充策略 public void insertFill(MetaObject metaObject) { log.info("start insert fill.... "); this.setFieldValByName("createTime",new Date(),metaObject); this.setFieldValByName("updateTime",new Date(),metaObject); } @Override //更新时的填充策略 public void updateFill(MetaObject metaObject) { log.info("start update fill.... "); this.setFieldValByName("updateTime",new Date(),metaObject); } }
- 现在在进行插入更新操作的时候,就会自动的填充创建时间和更新时间。
4. 乐观锁(version)
数据库添加version字段,对应实体类添加version属性
@Version private Integer vision;编写配置类
package com.simon.config; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @EnableTransactionManagement public class MyConfig { //注册乐观锁插件 @Bean public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor(){ return new OptimisticLockerInnerInterceptor(); } }测试
@Test public void contextLoads4() { //根据id查询,得到version User user = userMapper.selectById(1L); user.setAge(23); user.setName("Tony"); //现在a线程插队执行 User user1 = userMapper.selectById(1L); user1.setAge(23); user1.setName("Tony1"); userMapper.updateById(user1); //可以帮你自动的拼接sql语句 //这里修改的时候会加上version进行查询修改 //在多线程的情况下,a线程先修改完成后,b线程想要再次修改的话,就不能成功修改! //b线程再执行就会失败 int i = userMapper.updateById(user); }
总结:
在数据库中添加字段version字段,默认值为1,在每次进行修改的时候,就需要先获取version,然后修改成功后,version自动+1;如果多个线程同时操作这条数据时,后面执行的线程就会修改失败。
在多线程的情况下,使用乐观锁,可以避免数据发生错误,也就是线程之间修改数据的覆盖;保证了数据修改的安全性!

5. 查询操作(select)
@Test
public void contextLoads5() {
//通过id查询单个用户
User user = userMapper.selectById(1L);
System.out.println(user);
//通过多个id查询多条数据
List<User> users = userMapper.selectBatchIds(Arrays.asList(1L,2L,3L));
users.forEach(System.out::println);
//通过map作为查询条件进行查询
//我们还可以使用Wrapper进行封装
HashMap<String, Object> map = new HashMap<>();
map.put("id",1L);
map.put("name","Tony1");
List<User> map1 = userMapper.selectByMap(map);
map1.forEach(System.out::println);
//记录数
Integer count = userMapper.selectCount(null);
System.out.println(count);
}
6.删除操作(逻辑删除deleted)
@Test
public void contextLoads7() {
//根据id删除单个记录
userMapper.deleteById(1333599021827780610L);
//批量删除
userMapper.deleteBatchIds(Arrays.asList(1333586687944278018L,5L));
//map删除
HashMap<String, Object> map = new HashMap<>();
map.put("name","Tom");
userMapper.deleteByMap(map);
}
逻辑删除:在数据库中还是存在的,还是可以通过条件查询得到数据;管理员是可以通过一定的条件查询已经删除的数据
物理删除:直接从数据库中删除,数据库中是不存在的
- 在数据库中添加deleted字段:默认值为0,逻辑删除之后修改为1

- 实体类添加deleted属性,添加注解@TableLogic
@TableLogic//逻辑删除
private Integer deleted;
- 配置sql自动注入配置类
//逻辑删除配置,这个是最新版本的sql注入配置
@Bean
public LogicDeleteByIdWithFill logicDeleteByIdWithFill(){
return new LogicDeleteByIdWithFill();
}
//在3.2.0版本的配置类
@Bean
public ISqlInjector iSqlInjector(){
return new LogicSqlInjector();
}
- 配置properties文件
#配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
- 测试
@Test
public void contextLoads8() {
//根据id删除单个记录
userMapper.deleteById(1333599021827780610L);
}


7.分页查询(分页插件)
- 编写配置类
//分页插件配置,最新版本的这个配置类已经废弃掉了,但是还是可以使用
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
- 测试
@Test
public void contextLoads6() {
//需要一个分页对象,当前页,页面大小
Page<User> page = new Page<>(2,5);
userMapper.selectPage(page, null);
page.getRecords().forEach(System.out::println);
}
8.条件构造器
@Test
public void contextLoads9() {
//条件构造器wrapper
//类比map
QueryWrapper<User> wrapper = new QueryWrapper<>();
//是链式编程可以不断的.
wrapper
.isNotNull("name")
.isNotNull("email")
.ge("age",25);
List<User> list = userMapper.selectList(wrapper);
list.forEach(System.out::println);
}
9.性能分析插件
注意在mybatis-plus:3.2.0之后的版本移除了这个插件。可以设置sql查询的最大时间和对控制台sql语句进行格式化
- 配置类
//性能分析插件
@Bean
@Profile({"dev","test"})
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
// maxTime 指的是 sql 最大执行时长100ms
performanceInterceptor.setMaxTime(100);
//SQL是否格式化 默认false
performanceInterceptor.setFormat(true);
return performanceInterceptor;
}
- 配置properties文件
#性能插件配置,开发环境
spring.profiles.active=dev
- 测试执行语句
@Test
public void contextLoads9() {
//条件构造器wrapper
//类比map
QueryWrapper<User> wrapper = new QueryWrapper<>();
//是链式编程可以不断的.
wrapper
.isNotNull("name")
.isNotNull("email")
.ge("age",25);
List<User> list = userMapper.selectList(wrapper);
list.forEach(System.out::println);
}

版权声明:本文为weixin_45826188原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。