MyBatisPlus

发布于:2025-07-23 ⋅ 阅读:(19) ⋅ 点赞:(0)

快速入门

快速开始

使用MyBatisPlus的基本步骤: 

① 引入MybatisPlus依赖, 代替Mybatis依赖

<!--mybatis-plus依赖-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>

② 定义Mapper接口并继承BaseMapper

public interface UserMapper extends BaseMapper<User> {  
}

 之后直接调MyBatisPlus提供的方法就行(不用手写sql代码对于一些基础的sql语句)

 常见注解

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

MyBatisPlus有从实体类中获取信息的约定: 

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

例如这个类中类名User获取到表名User, id为主键, createTime获取到create_time字段

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

  • @TableName: 用来指定表名
  • @TaableId: 用来指定表中的主键字段信息
  • @TableField: 用来指定表中的普通字段信息 

id还有一项Type类型(如自增等)

IdType枚举: 

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

使用@TableField的常见场景: 

  • 成员变量名与数据库字段名不一致
  • 成员变量名以is开头, 且是布尔值
  • 成员变量名与数据库关键字冲突
  • 成员变量不是数据库字段

常见配置

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条件,可以满足日常开发的所有需求。

条件构造器的用法: 

  • QueryWrapper和LambdaQueryWrapper通常用来构建select、delete、update的where条件部分
  • UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用
  • 尽量使用LambdaQueryWrapper和LambdaUpdateWrapper, 避免硬编码
@Test
    void testQueryWrapper(){
        // 创建查询条件(查询id,username,info,balance,模糊查询username含o且balance大于等于1000)
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .select("id","username","info","balance")
                .like("username","o")
                .ge("balance",1000);
        // 执行查询
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
    
    @Test
    void testUpdateByQueryWrapper(){
        //要更新的数据(更新balance为2000)
        User user = new User();
        user.setBalance(2000);
        // 创建查询条件(查询username为jack的)
        QueryWrapper<User> wrapper = new QueryWrapper<User>()
                .eq("username","jack");
        //执行更新
        userMapper.update(user, wrapper);
    }

使用Lambda避免硬编码 

@Test
    void testQueryWrapper(){
        // 创建查询条件(查询id,username,info,balance,模糊查询username含o且balance大于等于1000)
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
                .select(User::getId,User::getUsername,User::getInfo,User::getBalance)
                .like(User::getUsername,"o")
                .ge(User::getBalance,1000);
        // 执行查询
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

    @Test
    void testUpdateByQueryWrapper(){
        //要更新的数据(更新balance为2000)
        User user = new User();
        user.setBalance(2000);
        // 创建查询条件(查询username为jack的)
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
                .eq(User::getUsername,"jack");
        //执行更新
        userMapper.update(user, wrapper);
    }

    @Test
    void testUpdateWrapper(){
        List<Long> ids = List.of(1L, 2L, 4L);
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<User>()
                .setSql("balance = balance - 200")
                        .in(User::getId, ids);
        userMapper.update(null, wrapper);
    }

自定义SQL

更新id为1、2、4的三条数据的balance减少200,之前写的这种方式把sql语句中的其中一部分写在了业务层。

@Test
    void testUpdateWrapper(){
        List<Long> ids = List.of(1L, 2L, 4L);
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<User>()
                .setSql("balance = balance - 200")
                        .in(User::getId, ids);
        userMapper.update(null, wrapper);
    }

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

  1. 基于Wrapper构建where条件
    @Test
    void testUpdate(){
        int amount = 200;
        List<Long> ids = List.of(1L, 2L, 4L);
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<User>().in(User::getId, ids);
        userMapper.updateById(wrapper, amount);
    }
  2. 在mapper方法参数中用Param注解声明wrapper变量名称,必须是ew
    void updateById(@Param("ew")LambdaUpdateWrapper<User> wrapper, int amount);
  3. 自定义SQL,并使用wrapper条件
    <update id="updateById">update user set balance = balance - #{amount} ${ew.customSqlSegment}</update>

Service接口

MP的Service接口使用流程

1. 自定义Service接口继承IService接口

public interface IUserService extends IService<User> {
}

2. 自定义Service实现类,实现自定义接口并继承ServiceImpl类

@Service
public class IUserServiceImpl 
            extends ServiceImpl<UserMapper, User> 
            implements IUserService {
}

IService的Lambda方法

用lambda方法可以直接构建条件更新操作最后必须加上.update()才能运行

//4.更新用户余额,如果余额不足则将用户状态改为2
        int remoney = user.getBalance() - money;
        lambdaUpdate().set(User::getBalance, remoney)
                .set(remoney <= 0, User::getStatus, 2)
                .eq(User::getId, id)
                .eq(User::getBalance, user.getBalance())//乐观锁
                .update();

 查询时查询一个用 .one(),多个用 .list(),分页用.page()。

return lambdaQuery()
                .like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, status)
                .ge(minBalance != null, User::getBalance, minBalance)
                .le(maxBalance != null, User::getBalance, maxBalance)
                .list();

 批量新增用户100000个

普通for循环插入

IService的批量插入 

扩展功能

代码生成器

使用插件来快速生成代码框架(实体类,controller,mapper等)

下载MyBatisPlus插件

先选config Database来选择要连接的数据库 

在选择Code Generator去配置要生成的框架

DB静态工具 

和IService里的方法几乎一样,但不同的是这里的都是静态方法要传入对应实体类的字节码文件,IService要注入对应实体类然后在泛型处填入。如果遇到两个Service相互注入就可以用静态工具(防止出现循环依赖的情况)。

逻辑删除

逻辑删除指并不是真正的删除而是在逻辑上删除(其实数据还在)例如:微信聊天记录,删除只是表面上删除,但实际上还在。

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

假设逻辑删除字段为deleted:

  • 删除操作:update user set deleted = 1 where id = 1 and deleted = 0;
  • 查询操作:selete * from user where deleted = 0; 

 mp为我们提供了简单的解决方法,不需要我们再去改动sql语句。

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted   # 全局逻辑删除的实体字段名,字段类型可以是boolean、integer
      logic-delete-value: 1       # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0   # 逻辑未删除值(默认为 0)

逻辑删除本身也有自己的问题,比如:

  • 会导致数据库表垃圾数据越来越多,影响查询效率
  • SQL中全都需要对逻辑删除字段做判断,影响查询效率

因此,我不太推荐采用逻辑删除功能,如果数据不能删除,可以采用把数据迁移到其它表的办法。

枚举处理器

在写项目时经常会用到状态字段,之前我们一直都是用1,2,3等数字表示状态但是如果状态过多,就很难记住各个数字表示什么状态,这时就可以创建一个枚举类来表示状态,而mybatisplus提供了枚举处理器可以让枚举类与数据库字段进行转换。

#配置类中进行配置
mybatis-plus:
  configuration:
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
@Getter
public enum UserStatus {
    NORMAL(1, "正常"),
    FREEZE(2, "冻结")
    ;
    @EnumValue  //注解表示数据库存的值是这个枚举的value
    private final int value;
    @JsonValue  // 此注解在谁上面查询到的返回值就是谁
    private final String desc;

    UserStatus(int value, String desc) {
        this.value = value;
        this.desc = desc;
    }
}

JSON处理器

Java中是没有JSON对应的数据类型的,之前是用字符串来接,但如果要对JSON中的一些内容进行操作,是非常麻烦的要转换类型,mp为我们提供了JSON处理器,可以直接转换。

先给JSON字段写一个实体类

package com.itheima.mp.domain.po;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor(staticName = "of")
@NoArgsConstructor
public class UserInfo {
    private Integer age;
    private String intro;
    private String gender;
}

 在实体类上加注解指定JSON处理器

 /**
     * 详细信息
     */
    @TableField(typeHandler = JacksonTypeHandler.class)
    private UserInfo info;


网站公告

今日签到

点亮在社区的每一天
去签到