Mybatis-Plus简介
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
支持数据库
- MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb
- 达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库
快速开始
- 创建数据库表
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');
创建springboot项目,导入依赖,导入mybatis-plus-boot-starter后不需要导入 MyBatis以及 MyBatis-Spring,会有版本冲突 ```xml
org.springframework.boot spring-boot-starter-web org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test com.baomidou mybatis-plus-boot-starter 3.0.5 mysql mysql-connector-java junit junit test
-
创建实体类
```java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
- 创建mapper接口,继承BaseMapper,自动装配后可以直接使用基本方法
```java
@Repository
public interface UserMapper extends BaseMapper
{
}
-
主启动类
```java
@MapperScan("com.example.mybatisplusdemo.mapper")
@SpringBootApplication
public class MybatisPlusDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusDemoApplication.class, args);
}
}
- 测试:
@Test
public void testSelect() {
System.out.println(("----- selectAll method test ------"));
List<User> userList = userMapper.selectList(null);
for (User user : userList) {
System.out.println(user);
}
日志配置
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
配置后即可在控制台查看日志
注解
@TableId
- 描述:主键注解
- 使用位置:实体类主键字段 | 属性 | 类型 | 必须指定 | 默认值 | 描述 | | :—- | :—- | :—- | :—- | :—- | | value | String | 否 | “” | 主键字段名 | | type | Enum | 否 | IdType.NONE | 指定主键类型 |
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 方法) |
ID_WORKER | 分布式全局唯一 ID 长整型类型(please use ASSIGN_ID ) |
UUID | 32 位 UUID 字符串(please use ASSIGN_UUID ) |
ID_WORKER_STR | 分布式全局唯一 ID 字符串类型(please use ASSIGN_ID ) |
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface TableId {
String value() default "";
IdType type() default IdType.NONE;
}
默认为IdType.NONE
主键生成策略
- 测试
@Test
public void insertTest(){
User user = new User();
user.setName("霸哥");
user.setAge(15);
user.setEmail("1009703142@qq.com");
userMapper.insert(user);
System.out.println(user);
}
此时显示的id为1489164848716582913,分布式系统全局唯一id生成,采用的是雪花算法
- 修改主键生成策略为自增
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
}
在数据库中自动生成的id为自增
@TableField
- 描述:字段注解(非主键)
测试字段填充策略:
数据库操作,添加字段
修改User属性 ```java // 插入时更新 @TableField(fill = FieldFill.INSERT) private Date createTime;
// 更新时更新 @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime;
-
创建handler实现MetaObjectHandler即可自动填充,注意要注入IOC中
```java
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date() ,metaObject);
this.setFieldValByName("updateTime",new Date() ,metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date() ,metaObject);
}
}
@Version
乐观锁插件
OptimisticLockerInnerInterceptor
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前 version
- 更新时,带上这个 version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果 version 不对,就更新失败
测试
- 添加字段,加上注解
// 乐观锁字段注释
@Version
private Integer version;
- 配置类,注册组件
```java
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
/**
- 旧版 */ @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); }
}
<br />新版使用以下
```java
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
/**
* 旧版
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
- 测试
// 乐观锁测试,模拟多线程
@Test
public void updateOptimisticTest(){
User user1 = userMapper.selectById(1L);
user1.setName("霸哥");
user1.setAge(15);
user1.setEmail("1009703142@qq.com");
User user2 = userMapper.selectById(1L);
user2.setName("Bug");
user1.setAge(18);
user1.setEmail("1435345314@qq.com");
userMapper.updateById(user2);
userMapper.updateById(user1);
}
字段只会更新user2的值。
@TableLogic
逻辑删除插件
- 数据库中增加deleted字段,并在实体类字段上添加注解
// 逻辑删除
@TableLogic
private Integer deleted;
- 配置组件(新版不用配置)
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
- yml中设置删除设定的值,配置logic-delete-field可以不用加注解
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)
- 测试 ```java @Test public void deleteTest() { userMapper.deleteById(1489164848716582917L); }
@Test public void selectTest() { userMapper.selectById(1489164848716582917L); }
<br />此时删除变为更新deleted操作,查询会自动带上deleted=0条件。
<a name="ba4ab757"></a>
# 分页插件
-
配置类中注册拦截器
```java
//Spring boot方式
@Configuration
@MapperScan("com.baomidou.cloud.service.*.mapper*")
public class MybatisPlusConfig {
// 旧版
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
}
- 测试:
@Test
public void pageTest() {
Page<User> page = new Page(1 , 3);
userMapper.selectPage(page, null);
page.getRecords().forEach(System.out::println);
// 获得总页数
System.out.println(page.getTotal());
}
代码生成器
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
- 引入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
配置代码生成器类
public class CodeGenerator {
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("peanut");
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.setUsername("root");
dsc.setPassword("LJLljl20020728.+");
dsc.setUrl("jdbc:mysql://localhost:3306/mybatis-plus?serverTimezone=UTC");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
//3、包的配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("user"); // 设置模块名
pc.setParent("com.example"); // 设置父包名
pc.setEntity("entity"); // 设置实体类包名
pc.setMapper("mapper"); // 设置mapper接口类包名
pc.setService("service"); // 设置service层包名
pc.setController("controller"); // 设置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 gmtUpdate = new TableFill("gmt_update", FieldFill.INSERT_UPDATE);
ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(gmtCreate);
tableFills.add(gmtUpdate);
strategy.setTableFillList(tableFills);
//乐观锁配置
strategy.setVersionFieldName("version");
strategy.setRestControllerStyle(true);//开启驼峰命名
strategy.setControllerMappingHyphenStyle(true);// 可映射风格localhost:8080/hello_id_2
mpg.setStrategy(strategy);
mpg.execute();//执行
}
}