MybatisPlus+mbg(代码自动生成器)
简介
非官方推出,而是别人开发出来的,对mybatis的加强工具(尽量不要和mybatis同时导入,避免冲突),侵入性小,自动注入了 CRUD,于jpa较为相似的。
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
日志配置
#日志输出
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
主键生成策略
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);
private int key;
IdType(int key) {
this.key = key;
}
}
雪花算法
分布式Long 类型id生成算法(全球唯一,一般用来生成订单号等….)
创建&更新时间
直接在数据库声明:
在代码级别的声明(需自定义处理器来处理):
@TableField(fill = FieldFill.INSERT) //使用该类注解是需要手动编写处理器来处理
Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE) //使用该类注解是需要手动编写处理器来处理
Date updateTime;
乐观锁(CAS)
概念:每次不加锁,假设没有冲突而去完成某项操作;如果发生冲突了那就去重试,直到成功为止。
ABA问题
当一个线程去修改一个v为A的变量,将其修改为B后又修改回A,另一个线程将预期的V和后来的V对比相同,则CSA成功,但是v是被人修改过的
解决办法:
为字段增加一个version字段,来保存版本,每次修改时会修改该version
自编译组件:
@Configuration
public class MyConfig {
@Bean
public OptimisticLockerInterceptor OptimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
分页插件(自带)
@Bean
public PaginationInterceptor PaginationInterceptor() {
return new PaginationInterceptor();
}
====================================================
//分页工具测试
@Test
void testPageHelper() {
//分页
Page<User> page = new Page<>(1,5);
userMapper.selectPage(page, null);
page.getRecords().forEach(System.out::println);
System.out.println("总页数:"+page.getTotal());
}
逻辑删除(回收站)
概念:不直接去删除,而是用一个变量的值来代表是否被删除
基本使用过程:
-
编写组件
//逻辑删除 @Bean public ISqlInjector LogicSqlInjector() { return new LogicSqlInjector(); }
-
添加注解逻辑删除pojo属性
@TableLogic private int deleted;//逻辑删除
-
配置文件配置逻辑删除的值
#逻辑删除设置 mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=0
性能分析插件
功能:可以通过限制一些sql的执行时间和格式化sql语句
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uHeX3wNA-1626420484571)(C:\Users\liuguangcheng\AppData\Roaming\Typora\typora-user-images\image-20210616204321065.png)]
//性能分析插件
@Bean
@Profile("dev") //必须配置环境
public PerformanceInterceptor PerformanceInterceptor(){
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setFormat(true);
performanceInterceptor.setMaxTime(5);
return performanceInterceptor;
}
条件构造器
作用:自动注入的CRUD只能满足小部分需求,大部分的复杂(单表)sql还是得通过条件构造器来编写
建议:多表查询需手动编写sql和mapper文件
用例:
//wrapper构造器
@Test
void testWrapper(){
QueryWrapper queryWrapper=new QueryWrapper();
queryWrapper.eq("name","lgc");
List list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}
代码生成器
依赖导入:
<!--代码生成器的必要引擎-->
<!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity-engine-core -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
编写一个main方法配置并执行删除器的代码:
public class CodeGenerator {
public static void main(String[] args) {
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置
GlobalConfig gc = new GlobalConfig();
//String projectPath = System.getProperty("user.dir");
gc.setOutputDir("D:\\Idea_workspace\\guli_parent\\service\\service-edu" + "/src/main/java");
gc.setAuthor("l");
gc.setOpen(false); //生成后是否打开资源管理器
gc.setFileOverride(false); //重新生成时文件是否覆盖
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setIdType(IdType.ID_WORKER_STR); //主键策略
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
gc.setSwagger2(true);//开启Swagger2模式
mpg.setGlobalConfig(gc);
// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost/guli?serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 4、包配置
PackageConfig pc = new PackageConfig();
//包:com.atguigu.eduservice
pc.setParent("com.lll");
pc.setModuleName("eduservice"); //模块名
//包:com.atguigu.eduservice.controller
pc.setController("controller");
//包:com.atguigu.eduservice.entity
pc.setEntity("entity");
//包:com.atguigu.eduservice.service
pc.setService("service");
//包:com.atguigu.eduservice.mapper
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("teacher");//对应数据库表名
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
}