文章目录
mybatis-plus是什么
mybatis-plus是mybatis的增强工具,在mybatis的基础上只做增强不做改变。
mybatis-plus特性
- 无侵入:不会改变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 操作智能分析阻断,也可自定义拦截规则,预防误操作
快速上手案例
- 导入依赖
implementation group: 'com.baomidou', name: 'mybatis-plus-boot-starter', version: '3.4.2'
runtimeOnly 'org.postgresql:postgresql'
- 创建实体类
@Data
public class TbUser {
private Integer id;
private String username;
private String password;
}
- 创建mapper接口。
说明:继承BaseMapper时,在泛型中填写对应的实体类。然后需要在启动类上添加@MapperScan("com.example.gradle.mapper")
注解,用于说明扫描路径。不需要写实现类,实现类是在运行时使用动态代理生成的。
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.gradle.bean.TbUser;
public interface UserMapper extends BaseMapper<TbUser> {
}
- 测试
在selectList()方法参数填null,表示查询所有。
@Autowired
private UserMapper userMapper;
public List<TbUser> getUser(){
return userMapper.selectList(null);
}
执行结果如下图:
补充:在配置文件中添加如下配置可以在控制台中看到执行的sql语句。
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
常用注解
1、@TableName()
用于映射数据库表名,如果不写mybatis-plus会将类名进行映射(能将骆驼峰命名自动映射到斜划线的命名方式)
2、@TableField()
用于映射字段名。
属性说明:
- exist:表示是否为数据库字段,如果实体类中的成员变量在数据库中没有对应的字段,则可以将exist设置为false。
- select:表示是否查询该字段
- fill:表示是否自动填充,将对象存入数据库的时候,由MyBatis Plus自动给某些字段赋值,常用的字段有create_time、update_time等,具体填充什么,需要编写处理器进行配合使用。
处理器:
@Component
public class MyMetaObjectHandle 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);
}
}
当插入时会调用insertFill()方法,当更新时会调用updateFill()方法。
测试结果:
3、@TableId()
用于映射主键。
type可以设置主键类型,主键的生成策略。共有如下选项:
public enum IdType {
/**
* 数据库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),
/**
* @deprecated 3.3.0 please use {@link #ASSIGN_ID}
*/
@Deprecated
ID_WORKER(3),
/**
* @deprecated 3.3.0 please use {@link #ASSIGN_ID}
*/
@Deprecated
ID_WORKER_STR(3),
/**
* @deprecated 3.3.0 please use {@link #ASSIGN_UUID}
*/
@Deprecated
UUID(4);
private final int key;
IdType(int key) {
this.key = key;
}
}
默认值是 NONE
总结:
- INPUT 如果开发者没有手动赋值,则数据库通过自增的方式给主键赋值,如果开发者手动赋值,则存入该值。
- AUTO默认就是数据库自增,开发者无需赋值。
- ASSIGN_ID 自动赋值,雪花算法(雪花算法生成的最终结果其实就是一个long类型的Java长整型数字,分布式ID)。
- ASSIGN_UUID主键的数据类型必须是String,自动生成UUID进行赋值。
4、@Version()
用于标记乐观锁,通过version字段来保证数据的安全性,当修改数据的时候,会以version 作为条件,当条件成立的时候才会修改成功。
测试结果如下:
5、@TableField()
通用枚举类注解,将数据库字段映射成实体类的枚举类型成员变量
案例:
import com.baomidou.mybatisplus.annotation.EnumValue;
public enum StatusEnum {
WORK(1,"上班"),
REST(0,"休息");
StatusEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
@EnumValue
private Integer code;
private String msg;
}
需要在配置文件中声明枚举类所在的包
type-enums-package:
com.example.gradle.enums
测试结果:
6、 @TableLogic()
用于映射逻辑删除字段
数据表添加 delete 字段,并且在实体类上添加注解,当删除的时候并不会把数据删掉,只会修改delete字段的值,在查询的时候也会自动过滤delete字段。
需要在配置文件中声明已删除和未删除的值是什么,如下0表示未删除,1表示已删除。
global-config:
db-config:
logic-not-delete-value: 0
logic-delete-value: 1
测试结果如下:
删除时:
查询时:
CURD操作
@Test
void save() {
TbUser tbUser = new TbUser();
tbUser.setUsername("李四");
tbUser.setPassword("123");
userMapper.insert(tbUser);
}
@Test
void update() {
TbUser tbUser = userMapper.selectById("1");
tbUser.setUsername("小明");
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("username", "王五");
userMapper.update(tbUser, queryWrapper);
}
@Test
void delete() {
// QueryWrapper queryWrapper = new QueryWrapper();
// queryWrapper.eq("id", "1411211044103897089");
// userMapper.delete(queryWrapper);
//多条件删除
QueryWrapper queryWrapper1 = new QueryWrapper();
HashMap<String, Object> mqp = new HashMap<>();
mqp.put("id", "1411217230412865538");
mqp.put("password", "123");
userMapper.deleteByMap(mqp);
}
@Test
void select() {
//查询全部
// List<TbUser> tbUsers = userMapper.selectList(null);
//单一条件查询
// QueryWrapper queryWrapper = new QueryWrapper();
// queryWrapper.eq("username","王五");
// queryWrapper.gt("version",2);
// System.out.println(userMapper.selectList(queryWrapper));
//模糊查询 %
// QueryWrapper queryWrapper = new QueryWrapper();
// %五
// queryWrapper.likeLeft("username", "五");
// System.out.println(userMapper.selectList(queryWrapper));
//排序
// QueryWrapper queryWrapper = new QueryWrapper();
// queryWrapper.orderByAsc("version");
// userMapper.selectList(queryWrapper).forEach(System.out::println);
//将返回的结果封装到map中,然后返回
// userMapper.selectMaps(queryWrapper).forEach(System.out::println);
//多条件查询
// QueryWrapper queryWrapper = new QueryWrapper();
// HashMap<String, Object> map = new HashMap<>();
// map.put("username", "王五");
// map.put("id", "1");
// queryWrapper.allEq(map);
// System.out.println(userMapper.selectList(queryWrapper));
}
分页查询
//分页查询
//第一个参数表示第几页,第二个参数表示每一页的大小
Page<TbUser> Page = new Page<>(1, 2);
Page<TbUser> result = userMapper.selectPage(Page, null);
//获取页面大小
System.out.println(result.getSize());
//获取结果总数
System.out.println(result.getTotal());
//获取查询结果
List<TbUser> records = result.getRecords();
System.out.println("---------------------------------");
records.forEach(System.out::println);
注意使用分页查询需要在配置类进行配置:
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}