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 操作智能分析阻断,也可自定义拦截规则,预防误操作
基础使用示例:
1、导入依赖坐标
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.5.3.2</version>
</dependency>
2、继承BaseMapper,调用mybatis-plus内置方法
// 不想努力直接继承mybatis-plus的家产 (Mapper层)
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
// 调用BaseMapper的方法 (Controller层)
void contextLoads() {
userMapper.selectById(1L);
}
这些BaseMapper的方法直接调用,大大提高开发效率! Mybatis-Plus官网:https://baomidou.com/
3、yaml配置
mybatis-plus:
type-aliases-package: com.forest.mp.domain.po # 别名扫描包
mapper-locations: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,默认值
configuration:
map-underscore-to-camel-case: true # 是否开启下划线和驼峰的映射cache-
enabled: false # 是否开启二级缓存
global-config:
db-config:
id-type: assign_id # id为雪花算法生成
update-strategy: not_null # 更新策略:只更新非空字段
高级用法-条件构造器
1、Mapper层的写法
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
2、Service层的写法
public interface UserService extends IService<User> {
boolean deductionUserMoney(Long id, Integer money);
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Override
public boolean deductionUserMoney(Long id, Integer money) {
User user = this.getById(id);
if (user.getStatus() == null || user.getStatus() == 2) {
throw new RuntimeException("该用户状态异常!");
}
user.setBalance(user.getBalance() - money);
return this.updateById(user);
}
}
3、Controller层的写法
@Api(tags = "用户相关接口")
@RestController("/users")
@RequiredArgsConstructor // lombok工具 构造必要的Bean
public class UserController {
private final UserServiceImpl userService; // 加上final可被lombok自动构造
@ApiOperation("新增用户")
@PostMapping
public boolean save(@ApiParam("用户Id") @RequestBody User user) {
return userService.save(user);
}
@ApiOperation("删除用户")
@DeleteMapping("/{id}")
public boolean delete(@ApiParam("用户Id") @PathVariable Long id) {
return userService.removeById(id);
}
@ApiOperation("根据id查询用户")
@GetMapping("/{id}")
public User get(@PathVariable Long id) {
return userService.getById(id);
}
@ApiOperation("扣减用户余额")
@PutMapping("/{id}/deduction/{money}")
public boolean deduction(@ApiParam("用户Id") @PathVariable Long id, @ApiParam("扣除的钱") @PathVariable Integer money) {
return userService.deductionUserMoney(id,money);
}
}
MP — 代码生成功能
1、安装Mybatis-plus插件
2、配置mysql连接
配置好url、用户名和密码
3、 点击code generator 填写配置
配置好,点击提交就大功告成啦!你会发现代码帮你自动生成好了。
静态工具查询
当service出现相互调用时,未避免循环依赖。可以使用Db静态工具来去调用。
用一个小的案例来讲解吧~
需求: ①改造根据id查询用户的接口,查询用户的同时,查询出用户对应的所有地址 ( 利用Db静态工具 )
User user = this.getById(id);
if (user.getStatus() == null || user.getStatus() == 2) {
throw new RuntimeException("该用户状态异常!");
}
List<Address> addressList = Db.lambdaQuery(Address.class).eq(Address::getUserId, user.getId()).list();
UserVo userVo = new UserVo();
BeanUtils.copyProperties(user, userVo);
userVo.setAddressList(addressList);
return userVo;
逻辑删除
逻辑删除就是基于代码逻辑模拟删除效果,但并不会真正删除数据。思路如下:
-
- 在表中添加一个字段标记数据是否被删除
- 当删除数据时把标记置为1
- 查询时只查询标记为0的数据
例如逻辑删除字段为deleted:
MybatisPlus提供了逻辑删除功能,无需改变方法调用的方式,而是在底层帮我们自动修改CRUD的语句。我们要做的就是在application.yaml文件中配置逻辑删除的字段名称和值即可:
1、将数据表添加一个deleted字段
`deleted` bit(1) DEFAULT b'0' COMMENT '逻辑删除'
2、修改yml配置文件
mybatis-plus: global-config: db-config: logic-delete-field: deleted # 全局逻辑删除的实体字段名,字段类型可以是boolean, integer logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
枚举处理器
业务场景(假设:User类中有一个用户状态字段)
我们需要用枚举类型来代表user的状态,可以数据库的字段是int类型。两者并不相通,于是我们与要一个预处理器来自动的将枚举类型的字段转换为int类型的字段,并存储到数据库里面。
1、使用@EnumValue
注解来标记需要处理的枚举类
@Getter
public enum UserStatus {
NORMAL(1, "正常"),
FROZEN(0, "冻结"),
;
@EnumValue /* 标记 mybatis-plus 需要处理的枚举 */
@JsonValue /* SpringMvc 在处理enum返回值的时候默认会返回`NORMAL`这类英文的数据。这并不优雅,我们可以用`@JsonValue`来指定返回的是value还是desc还是enum */
private final int value;
private final String description;
UserStatus(int value, String description) {
this.value = value;
this.description = description;
}
}
2、修改yml配置文件,指定枚举的预处理器。
mybatis-plus:
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
视频链接:https://www.bilibili.com/video/BV1S142197x7?t=89.6&p=17
JSON处理器
当数据表出现json类型的字段时,Java实体类无法与其对应。这时可以使用json处理器来将json类型的字段转换为Java实体类。
1、创建于MySQL字段json类型对应的实体类
@Data
public class UserDetail {
private Integer age;
private String intro;
private String gender;
}
1、添加类型预处理器
/* 开启自动结果映射 */
@TableName(value = "user", autoResultMap = true)
@ApiModel(description = "用户表单实体")
@Data
public class User {
@ApiModelProperty("用户id")
private Long id;
@ApiModelProperty("用户名")
private String username;
@ApiModelProperty("密码")
private String password;
@ApiModelProperty("注册手机号")
private String phone;
/* 添加类型处理器 */
@TableField(typeHandler = JacksonTypeHandler.class)
@ApiModelProperty("详细信息")
private UserDetail info;
@ApiModelProperty("使用状态(1正常")
private Integer status;
@ApiModelProperty("账户余额")
private Integer balance;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
}
分页插件
mybatis-plus自带的有很多插件,其中最常用的就是分页插件,我们一起来看看把
1、添加MybatisConfig
配置类
@Configuration
public class MybatisConfiguration {
@Bean /* 重写Mybatis-plus拦截器哦 */
public MybatisPlusInterceptor mybatisPlusInterceptor() {
// 创建一个mybatis-plus拦截器
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
// 创建MySql分页插件,将他添加到mybatis-plus里
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
return mybatisPlusInterceptor;
}
}
2、使用分页查询
void contextLoads() {
int pageNum = 1;
int pageSize = 10;
/* 开启分页查询 */
Page<User> page = new Page<>(pageNum, pageSize);
page.addOrder(new OrderItem("balance", true)/* 排序字段,是否降序 */);
page.addOrder(new OrderItem("id", true)/* 排序字段,是否降序 */);
/* lambda条件构造器 */
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>()
.eq(User::getStatus, 1);
/* 开始查询 */
Page<User> userPage = userMapper.selectPage(page, lambdaQueryWrapper);
/* 结果封装 */
long total = userPage.getTotal();
List<User> records = userPage.getRecords();
}
原理: MyBatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息。
固定的约定
如果你没有遵守约定,也不用担心Mybatis-Plus 自带的注解可以自定义的配置!
自定义配置
MybatisPlus 中比较常用的几个注解如下:
@TableName
— 用来指定表名
@Tableld
— 用来指定表中的主键字段信息
@TableField
— 用来指定表中的普通字段信息
IdType枚举:AUTO:
AUTO:数据库自增长
INPUT:通过set方法自行输入
ASSIGN_ID: 分配 ID·接口IdentifierGenerator的方法nextld来生成id默认实现类 为DefaultldentifierGenerator雪花算法
使用@TableField的常见场景:
- 成员变量名与数据库字段名不一致
- 成员变量名以is开头,且是布尔值
- 成员变量名与数据库关键字冲突
- 成员变量不是数据库字段
- 成员变量名与数据库字段名不一致
总结:
灵魂拷问?
1、MybatisPlus是如何获取实现CRUD的数据库表信息的?
2、MybatisPlus的常用注解有哪些?
3、IdType的常见类型有哪些?
4、使用@TableField的常见场景是?
相关文章:
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://www.forest88.top/2024/05/04/mybatis-plus-%e5%9f%ba%e7%a1%80%e6%95%99%e7%a8%8b/
FGHRSH 的博客
666
天才阿梓博主
@FGHRSH 的博客: 学到了吧,哈哈