MyBatis-Plus入门

发布于:2024-03-29 ⋅ 阅读:(17) ⋅ 点赞:(0)


MyBatisPlus

MyBatisPlus也是一款数据持久持久层的框架,他是对MyBatis的一个增强。对于一个项目MyBatisPlus可以做到无侵入的引入到项目中进行使用,并不影响MyBatis的使用。其支持一下特性:

  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作

  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题

  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码

  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询

  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询

  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

基本使用

引入Maven依赖

<!-- 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>

在启动类上添加@MapperScan扫描注解指定mapper目录

@MapperScan("com.hhy.mp.mapper")

在Mapper接口拓展MyBatisPlus提供的 BaseMapper接口并指定对应的泛型

public interface UserMapper extends BaseMapper<User> {
    
}

直接注入Mapper接口即可使用对应的CRUD方法

在这里插入图片描述

注意事项&常用注解

MyBatisPlus通过扫描实体类,并通过反射获取实体类信息作为数据库表信息。

MyBatisPlus使用时需要遵守的约定:

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

如果我们没有遵守约定的话,就需要通过注解来指定对应的名称。

MybatisPlus中比较常用的几个注解如下:

@TableName:用来指定表名

@TableId:用来指定表中的主键字段信息

@TableField:用来指定表中的普通字段信息

IdType枚举:

  • AUTO:数据库自增长
  • INPUT:通过set方法自行输入
  • ASSIGN_ID:分配 ID,接口IdentifierGenerator的方法nextId来生成id,默认实现类为DefaultIdentifierGenerator雪花算法

使用@TableField的常见场景:

  • 成员变量名与数据库字段名不一致
  • 成员变量名以is开头,且是布尔值,MyBaits会将is去掉当成字段
  • 成员变量名与数据库关键字冲突
  • 成员变量不是数据库字段
@TableName("tb_user")
public class User {
    @TableId(value="id",type=IdType.AUTO)
    private Long id;
    @TableField("username")//成员变量名与数据库字段名不一致
    private String name;
    @TableField("is_married")//成员变量名以is开头,且是布尔值,MyBaits会将is去掉当成字段
    private Boolean isMarried;
    @TableField("`order`")//成员变量名与数据库关键字冲突
    private Integer order;
    @TableField(exist = false)//成员变量不是数据库字段
    private String address;
}

注解官方文档

配置文件

MyBatisPlus的配置项继承了MyBatis原生配置和一些自己特有的配置。例如:

注解的优先级时高于配置文件的

mybatis-plus:
  type-aliases-package: com.hhy.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配置官方文档

核心功能

条件构造器

MyBatisPlus页提供了复杂SQL的构造,通过条件构造器就可以构造复杂SQL。

在这里插入图片描述

基本使用

进行复杂一点的查询和修改

@Test
void select() {
    // 查询名字里包含o并且余额大于等于800的用户
    QueryWrapper<User> queryWrapper = new QueryWrapper<User>().select("id", "username", "info", "balance")
        .like("username", "o").ge("balance", 800);
    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);

    // 更新的值
    User user = new User();
    user.setBalance(2000);
    // 更新条件
    UpdateWrapper<User> wrapper = new UpdateWrapper<User>().eq("username","jack");
    userMapper.update(user,wrapper);


    // 需求:更新id为1,2,4的用户的余额,扣200
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>().setSql("balance = balance - 200").in("id", 1, 2, 4);
    userMapper.update(null,updateWrapper);
}

建议使用Lambda的这种写法,配和方法引用来使用

这种方式是通过反射来获取类型,这种方式没有使用硬编码

@Test
void select() {
    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>().select(User::getId, User::getUsername, User::getInfo,User::getBalance)
        .like(User::getUsername, "o").ge(User::getBalance, 800);
    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}

条件构造器的用法:

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

自定义SQL

我们可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分。

需求:将id在指定范围的用户(例如1、2、4 )的余额扣减指定值,如果不想在业务层编写SQL代码的话,这个需求用自定义SQL实现

void select() {
    List<Long> idList = new ArrayList<Long>(){
        {
            add(1L);
            add(2L);
            add(4L);
        }
    };
    int amount = 200;
    // 1.构造条件
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>().in(User::getId, idList);
    // 2.自定义SQL方法调用
    userMapper.updateBlanceByIds(wrapper, amount);
}
// 在mapper方法参数中用Param注解声明wrapper变量名称,必须是ew
void updateBlanceByIds(@Param("ew") LambdaQueryWrapper<User> wrapper,@Param("amount") int amount);
<update id="updateBlanceByIds">
        UPDATE user SET balance = balance - #{amount} ${ew.customSqlSegment}
    </update>

最后生成的SQL:UPDATE user SET balance = balance - ? WHERE (id IN (?,?,?))

IService接口

条件构造器Wrapper是为了简化Mapper的SQL编写,而IService接口是为了简化Service层的代码编写。通用 Service CRUD 封装IService 接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆。

Iservice是MyBatisPlus提供的接口而ServiceImpl是该接口的实现类,提供了大量的CRUD方法

在这里插入图片描述

  • UserService是我们自己定义的接口,UserServiceImpl是我们自己定义的实现类
  • 当UserService拓展了IService后,UserServiceImpl就要实现里面的大量方法
  • 此时就可以继承MyBatisPlus提供的ServiceImpl类就需要重写大量方法了,因为ServiceImpl已经帮我们实现了对应方法

IService的使用

先在自己定义的业务接口拓展MyBatisPlus提供的IService并指定要操作的数据泛型

// 拓展IService
public interface UserService extends IService<User> {
}

接着在对于业务实现类继承MyBatisPlus提供的ServiceImpl类并指定泛型参数:

  • 参数1为要调用的Mapper
  • 参数2为Mapper操作的数据对象

再实现对应的业务接口


public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
}

Iservice提供了对应的lambdaUpdate()lambdaQuery()来构造复杂更新和查询

IService批量新增

我们知道批量新增数据和一条一条插入数据的性能差距是非常大的,因为每一次insert都都是一次网络请求。

假设要插入10w条数据,就可以使用MyBitsPlus的批量插入,因为MyBitsPlus的批量新增,基于预编译的批处理,性能不错

10w条数据每次插入1000条数据,就会把1000条SQL拼接成一条insert into user ... values (...),(...),(...),效率就会非常高,如果接直接插入10w条数据的话会占用内存空间。通过saveBatch()方法就能实现批量插入。

需要注意的是:1000条插入数据是批量提交,当MySQL依旧是一条一条执行的。如果需要批量执行,则需要开启rewriteBatchedStatements=true参数


本文含有隐藏内容,请 开通VIP 后查看