Mybatis-Plus 总结
狂神课程笔记
快速入门 https://baomidou.com/guide/#%E7%89%B9%E6%80%A7
简介
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
使用第三方组件:
入门
1、导入对应的依赖
2、研究依赖如何配置
3、代码如何编写
4、提高扩展技术的能力
导入依赖
<!--mybatis-plus 是自己开发的,非官方的!-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1.tmp</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
编写pojo文件
编写mapper接口
@Repository 配置注解
继承BaseMapper<类型> 类 添加泛型。
@Repository
public interface UserMapper extends BaseMapper<User> {
}
@MapperScan(“mapper包名”)在主程序开启扫描,后期再MybatisPlusConfig配置类中开启
@MapperScan("com.lt.mapper")
配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl # 自带日志
实体中的属性类型用基础类型的包装类
插入
插入测试 输出未设置的id

未设置主键id,执行insert方法却自动生成id
主键生成策略

分布式系统唯一id生成
默认生成会执行 雪花算法 生成
SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id。在分布式系统中的应用十分广泛,且ID 引入了时间戳,基本上保持自增的。
这 64 个 bit 中,其中 1 个 bit 是不用的,然后用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号。
https://blog.csdn.net/lq18050010830/article/details/89845790
如果插入时未设置主键生成策略,则默认ID_WORKER
public enum IdType {
//数据库ID自增
AUTO(0),
//该类型为未设置主键类型
NONE(1),
//用户输入ID
//该类型可以通过自己注册自动填充插件进行填充
INPUT(2),
/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
//全局唯一ID (idWorker)
ID_WORKER(3),
//全局唯一ID (UUID)
UUID(4),
// 字符串全局唯一ID (idWorker 的字符串表示)
ID_WORKER_STR(5);
自增策略 数据库id也要设置自增,否则会报错
@TableId(type = IdType.AUTO)
private Long id;
修改 通过条件自动拼接动态sql 根据id修改传入参数的是user类型
public void update(){
User user = new User();
//通过条件自动拼接动态sql
user.setId(5L);
user.setAge(12);
//根据id修改传入参数的是user类型
int result = userMapper.updateById(user);
System.out.println(result);
}
自动填充
1.数据库级别的填充
自动填充时间 默认当前时间戳 勾选更新 低版本不支持 5.7以上[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-llXgLrvT-1607397832345)(…/笔记图片/image-20201202135009868.png)]
在表中新增字段 create_time 、update_time(默认CURRENT_TIMESIAMP)
Mybatis-Plus 自带驼峰标识
但是如果我们不设置mybstis plus 默认的驼峰式编码,mybatis-plus 则会默认把驼峰式编码userCode(数据库是userCode)装换成 user_code, 这种下划线格式的字段,这时你会发现你的代码会出错,它会提示你user_code字段不存在
appliction.yml 里设置 关闭驼峰式编码
mybatis-plus:
configuration:
# 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属性名 aColumn(驼峰命名) 的类似映射
map-underscore-to-camel-case: false
填充 创建时间和修改时间
2.代码级别的填充
在属性上添加填充注解
//自动填充字段 插入当前时间
@TableField(fill = FieldFill.INSERT) //fill 填充
private Date createTime;
//插入修改的当前时间
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
创建处理器 handler 定义类 MyMetaObjectHandler 实现MetaObjectHandler接口
@Slf4j // 导入日志
@Component //一定不要忘记把处理器加到IOC容器中
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insertFill");
//设置要插入字段的名,值和方法
this.setFieldValByName("createTime",new Date(),metaObject); //低版本使用
this.setFieldValByName("updateTime",new Date(),metaObject);
}
//更新的填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start updateFill");
//设置要更新字段的名,值和方法
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
版本不同使用方法也不同
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本3.3.0(推荐)
// 或者
this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
乐观锁
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
字段上加上@Version注解
@Version
private Integer version;
说明:
- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下
newVersion = oldVersion + 1 newVersion会回写到entity中- 仅支持
updateById(id)与update(entity, wrapper)方法 - 在
update(entity, wrapper)方法下,wrapper不能复用!!!
查询
//查询全部
List<User> users = userMapper.selectList(null);
//根据id查询
@Test
public void select01(){
User user = userMapper.selectById(2L);
System.out.println(user);
}
//批量查询
@Test
public void select02(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1,2,3));
for (User user:users) {
System.out.println(user);
}
}
//条件查询 map 方法之一
@Test
public void select03(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","L");
List<User> user = userMapper.selectByMap(map);
System.out.println(user);
}
分页
1、原始的limit进行分页
2、pageHelper 第三方插件
3、Mybatis-Plus中也内置了分页插件!
1.注册插件
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
return paginationInterceptor;
}
2.测试
public void page(){
//从0开始,查询三个
Page<User> page = new Page<>(0,3);
userMapper.selectPage(page,null);
//输出查询结果
page.getRecords().forEach(System.out::println);
//数据总条数
page.getTotal();
}
逻辑删除
相当于回收站,删除了只是改变数据中的delete字段(从0到1),并没有直接删除数据。
logic 逻辑
1.注册 Bean(3.1.1开始不再需要这一步):
@Configuration
public class MyBatisPlusConfiguration {
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
}
2.配置
#逻辑删除设置
#默认为0,删除为1
#全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
mybatis-plus.global-config.db-config.logic-delete-field=flag
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
3.全局逻辑删除: 3.3.0开始支持
如果公司代码比较规范,比如统一了全局都是flag为逻辑删除字段。
使用此配置则不需要在实体类上添加 @TableLogic。
但如果实体类上有 @TableLogic 则以实体上的为准,忽略全局。 即先查找注解再查找全局,都没有则此表没有逻辑删除。
@TableLogic
private Integer deleted; //flag就不用加注解
性能优化 (新版已无)
我们在平时的开发中,会遇到一些慢sql。测试!druid…
作用:性能分析拦截器,用于输出每条SQL语句及执行时间
MP也提供性能分析插件,如果超过这和时间就会停止运行
插件配置
@Bean
@Profile({"dev","test"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100);// ms 设置sql执行的最大时间,如果超过就停止
performanceInterceptor.setFormat(true);
return new PerformanceInterceptor();
条件查询
wrapper 包装
//条件查询
@Test
public void select04(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
//条件不能为空
.isNull("name")
.isNotNull("email")
//年龄大于十二
.ge("age",12);
userMapper.selectList(wrapper).forEach(System.out::println);
}
//单个查询
@Test
public void select05(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
//查询姓名为L的用户
wrapper.eq("name","L");
User user = userMapper.selectOne(wrapper);
System.out.println(user);
}
//查询在什么到什么之间的总个数
@Test
public void select06(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
//查询年龄在20到30之间的总个数
wrapper.between("age",20,30);
Integer integer = userMapper.selectCount(wrapper);
System.out.println(integer);
}
//模糊查询
@Test
public void select07(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
//名字里边包含 a 的,email里不包含2的
wrapper
.like("name","a")
.notLike("email",2);
userMapper.selectMaps(wrapper).forEach(System.out::println);
}
代码生成器
dao、pojo、conrtroller、service自动生成
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、 Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
依赖
<!--mybatis-plus 是自己开发的,非官方的!-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<!-- 模板引擎 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<!--swagger-->
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
代码
package com.util;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
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 AutoCode {
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("LT");
gc.setOpen(false);
gc.setFileOverride(false); // 是否覆盖
gc.setServiceName("%sService"); // 去Service的I前缀
gc.setIdType(IdType.ID_WORKER);
gc.setDateType(DateType.ONLY_DATE);
gc.setSwagger2(true);
mpg.setGlobalConfig(gc);
//2、设置数据源
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/mybatis-plus? useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("admin");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
//3、包的配置
PackageConfig pc = new PackageConfig();
// pc.setModuleName("blog");
pc.setParent("com.lt");
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);
// 自动lombok
strategy.setEntityLombokModel(true);
strategy.setLogicDeleteFieldName("deleted");
// 自动填充配置
TableFill gmtCreate = new TableFill("create_time", FieldFill.INSERT);
TableFill gmtModified = new TableFill("modified_time", 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();
//执行
}
}