MyBatis-Plus

Mybatis-plus

快速入门

导入

mybatis-plus依赖中含有mybatis依赖 所以直接更换依赖即可 导入mybatis依赖

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>

定义mapper接口继承BaseMapper 其中BaseMapper对象中泛型为mapper操作的实体类泛型

常见注解

MyBatisPlus通过扫描实体类 并且基于反射得到实体类信息作为数据库表信息 而且有以下约定

  • 类名驼峰转下划线作为表名
  • 名为id字段作为主键
  • 变量名驼峰转下划线作为表字段名

MyBatis中有三个常见注解

  • @TableName 来指定表名
  • @TableId 来指定表中主键
    • value是主键名
    • type是主键的增长策略 AUTO是自增长 INPUT通过set方法注入 ASSIGN_ID通过雪花算法来生成id 默认雪花算法生成Long型id
  • @TableField 来指定普通字段名 且常见场景如下
    • 变量名和数据库名不一致
    • 变量名以is开头 且是布尔值
    • 变量名和数据库关键字冲突 比如order和order by就冲突了
    • 变量名不是数据库字段 需要使用转义字符

常用配置

MyBatisPlus继承了mybatis的基础配置和一些特有配置

mybatis-plus:
  type-aliases-package: com.itheima.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 # 更新策略:只更新非空字段

核心功能

条件构造器

MyBatisPlus支持各种复杂where条件 都是通过Wrapper来构造的

条件构造器的用法

  • QueryWrapper和LambdaQueryWrapper通常来构建select delete update的where条件部分
  • UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用
  • 尽量使用LambdaQueryWrapper和LambdaUpdateWrapper 避免硬编码

自定义sql

Where条件用mp来写 剩余部分用xml自定义来写 从而组装完整的sql语句 分为以下步骤

  • 基于Wrapper构建where条件
  • 在mapper方法中调用@Param注解指定wrapper名称 必须是ew
  • 自定义sql 构建完整语句

Service接口

要需要实现分两步

  1. 自定义接口继承IService接口 从而自定义接口有所有方法声明
    public interface IUserService extends IService<User>
  2. 实现类继承IServiceImpl实现类 从而实现类有所有方法实现
    public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService

IService开发基础功能接口

首先注意的是注入的时候用构造函数来注入 可以使用lombok来注入 在类上使用@RequiredAgrsConstructor来通过注入 在类中直接@private final IUserService userService即可

  • 可以解决循环依赖的问题 循环依赖直接抛异常
  • 在测试方法里也更好用 直接用构造函数即可 而autowired还需要反射
  • 不可变性 用final定义保证变量不会被修改

使用lambdaUpdate的时候 构建完sql语句记得跟上.update() 这个才是真正执行update语句 上面全都是构建sql语句

        lambdaUpdate()
                .set(User::getBalance, remain)
                .set(remain < 0,User::getStatus,2)
                .eq(User::getId,id)
                .eq(User::getBalance,user.getBalance())
                .update();

批量处理

  • 普通for循环插入
    速度极差
  • IService批量插入
    使用批处理的时候采用的是预编译 比如十万条数据 每一千条发送一个sql 默认是发送一千条sql 但是这样性能还是会很慢
  • 开启rewriteBatchedStatements=true参数
    可以将一千条sql拼成一条sql语句 性能最好
    在配置文件里jdbc的配置中spring: datasource: url: jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
    后面拼上&rewriteBatchedStatements=true就可以实现拼接sql了

扩展功能

Db静态工具

方便解决循环依赖的问题
比如需求是 根据id查询用户 查询用户的同时查询用户对应地址根据用户id查询收货地址 并且验证用户状态
这两个需求分别需要在UserService中注入AddressService和在AddressService中注入UserService 也就是循环依赖 因此发生问题 如果采用@Autuwired注入 编译器不会报错 如果是定义静态常量用构造器注入 编译器会报循环依赖的错误
但是springboot不是解决循环依赖了吗 通过三级缓存?
解决该问题就是用Db静态工具 不需要再注入其他的Service 只需要传一个字节码文件 通过反射 就可以实现sql语句查询List<Address> addresses = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();

逻辑删除

也就是当购物订单用户想要删除的时候 在用户端显示删除了该数据 但是商家端不会删除 因此采用的策略就是逻辑删除 思路如下

  • 在表中添加一个字段标记数据是否被删除
  • 当删除数据时把标记修改为1
  • 查询时只查询数据为0的

mybatis-plus对逻辑删除做了适配 只需要在yaml文件中配置即可

但是同样的 逻辑删除存在一些问题

  • 会导致数据库垃圾数据越来越多 影响查询效率
  • sql中全部都需要对逻辑字段进行判断 影响查询效率

还有一种方法是新开一张表 采用数据迁移的方式来

枚举处理器

当数据库中和PO中出现要从枚举类型转成其他类型时 就可以通过@EnumValue来明确枚举中的变量哪一个跟数据库字段是对应的
然后在配置文件中配置

JSON处理器

在表中有json字段的属性info 而在idea中是用string来接收的 mp会自动进行转换 但是如果定义一个info对象来接收 就做不到了 因此需要进行配置

  • @TableField标记开启json处理
  • 因为对象中嵌套了另一个对象 因此需要在表名的@TableName开启自动ResultMap封装处理

插件功能

分页插件

使用分页插件首先需要在配置类里注册分页插件 mp的插件是基于拦截器实现的 会在所有业务到达数据库之前拦截然后实现相关功能

然后Page<User> page = Page.of(pageNo,pageSize);就可以直接使用了 通过静态方法传参 得到page对象 还可以通过add.Order来对该对象进行排序 调用service的page方法查询
返回的对象其实和定义的page对象是同一个对象 然后里面有各种信息 total总条数 pages总页数 records数据

posted @ 2025-08-12 09:20  big4mart  阅读(50)  评论(0)    收藏  举报