一、简介
1、Mybatis-plus是什么
MyBatis-Plus(简称MP)是一个MyBatis的增强工具,在MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
官方愿景
我们的愿景是成为MyBatis最好的搭档,就像[魂斗罗]中的1P、2P,基友搭配,效率翻倍。
2、特性
-
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
-
损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
3、支持数据库
任何能使用
MyBatis
进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下,如果不在下列表查看分页部分教程 PR 您的支持。
-
MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb,informix,TDengine,redshift
-
达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库,优炫数据库
4、框架结构
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
二、helloworld
1.前置要求
-
熟悉SSM
-
熟悉Springboot
-
熟悉Maven
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, '张三', 18, 'test1@baomidou.com'),
(2, '李四', 20, 'test2@baomidou.com'),
(3, '王五', 28, 'test3@baomidou.com'),
(4, '赵六', 21, 'test4@baomidou.com'),
(5, '田七', 24, 'test5@baomidou.com');
3.SpringBoot项目
三、注解
@TableName
表名注解,标识实体类对应的表
解决类名与数据库中的表名不一致问题 @TableName("user_info")
@Tableld
-
主键注解
-
使用位置:实体类主键字段
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 主键字段名 |
type | Enum | 否 | IdType.NONE | 指定主键类型 |
其中,ldType主键类型说明
在数据库中设置字段为自增,在实体类上加入 @Tableld(type = IdType.AUTO)
如果不设置自增,id会通过雪花算法进行生成
值 | 描述 |
---|---|
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 ) |
@TableField
字段注解:解决实体类属性名与表中字段名不一致的问题
eg:@TableField("value = "email")
//此字段在数据库中的表中不存在
@TableField(exist = false)
private String status;
@TableField(select = false):查询时不会在查这个字段
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 数据库字段名 |
exist | boolean | 否 | true | 是否为数据库表字段 |
condition | String | 否 | "" | 字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s} ,参考(opens new window) |
update | String | 否 | "" | 字段 update set 部分注入,例如:当在version字段上注解update="%s+1" 表示更新时会 set version=version+1 (该属性优先级高于 el 属性) |
insertStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例:NOT_NULL insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>) |
updateStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例:IGNORED update table_a set column=#{columnProperty} |
whereStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例:NOT_EMPTY where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if> |
fill | Enum | 否 | FieldFill.DEFAULT | 字段自动填充策略 |
select | boolean | 否 | true | 是否进行 select 查询 |
keepGlobalFormat | boolean | 否 | false | 是否保持使用全局的 format 进行处理 |
jdbcType | JdbcType | 否 | JdbcType.UNDEFINED | JDBC 类型 (该默认值不代表会按照该值生效) |
typeHandler | Class<? extends TypeHandler> | 否 | UnknownTypeHandler.class | 类型处理器 (该默认值不代表会按照该值生效) |
numericScale | String | 否 | "" | 指定小数点后保留的位数 |
@TableLogic
表字段逻辑处理注解(逻辑删除)
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 逻辑未删除值 |
delval | String | 否 | "" | 逻辑删除值 |
物理删除:直接删除,不存在了
逻辑删除:不会真正的删除了
使用步骤:
-
yml
mybatis-plus: global-config: db-config: logic-not-delete-value: 0 logic-delete-field: deleted #全局逻辑删除的实体字段名,配置后可不用@TableLogic注解 logic-delete-value: 1
-
pojo
@TableLogic private String deleted;
User(id=1, name=张三, age=18, email=test1@baomidou.com, status=null, deleted=0) User(id=2, name=李四, age=20, email=test2@baomidou.com, status=null, deleted=0) User(id=3, name=王五, age=28, email=test3@baomidou.com, status=null, deleted=0) User(id=4, name=赵六, age=21, email=test4@baomidou.com, status=null, deleted=0) User(id=5, name=田七, age=24, email=test5@baomidou.com, status=null, deleted=0)
UPDATE user SET deleted='1' WHERE id=? AND deleted='0'
四、查询
1.分页查询
-
配置分页拦截器
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); //分页拦截器 return mybatisPlusInterceptor; }
-
测试
@Test public void testGetAll2(){ Page<User> page = new Page<>(1,3); //从几页开始分,一页几条数据 userMapper.selectPage(page,null); System.out.println("总数" + page.getTotal()); List<User> records = page.getRecords(); for (User record : records) { System.out.println(record); } }
2.条件构造器
-
常规使用
@Test public void testSelect(){ //查询年龄>20,姓赵,降序排序 QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.gt("age",20); wrapper.likeRight("name","赵"); wrapper.orderByDesc("id"); List<User> userList = userMapper.selectList(wrapper); for (User user : userList) { System.out.println(user); } }
弊端:有可能数据库的字段名写错,找不到错误
-
推荐
@Test public void testSelect2(){ //查询年龄>20,姓赵,降序排序 LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.gt(User::getAge,20); wrapper.likeRight(User::getName,"赵"); wrapper.orderByDesc(User::getId); List<User> userList = userMapper.selectList(wrapper); for (User user : userList) { System.out.println(user); } }
五、代码生成器
导依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
代码:
FastAutoGenerator.create("url", "username", "password")
.globalConfig(builder -> {
builder.author("baomidou") // 设置作者
.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir("D://"); // 指定输出目录
})
.dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
// 自定义类型转换
return DbColumnType.INTEGER;
}
return typeRegistry.getColumnType(metaInfo);
}))
.packageConfig(builder -> {
builder.parent("com.baomidou.mybatisplus.samples.generator") // 设置父包名
.moduleName("system") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("t_simple") // 设置需要生成的表名
.addTablePrefix("t_", "c_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();