Mybatis-Plus

3,313 阅读4分钟

Mybatis-Plus常用点

本文章主要针对于mybatis-plus的一些功能、使用细节的梳理,并没有关于它的语法、方法进行整理,使用方法请自行查阅其他文章。

1. yml配置

以下为整理的常用yml配置,配置后无需配置mybatis且无需引入mybatis依赖

mybatis-plus:
  mapper-locations: classpath:mapper/**/*.xml  # mapper映射文件(默认存在)
  type-aliases-package: com.itheima.mp.demain # 别名包
  configuration:
    map-underscore-to-camel-case: true # 是否开启下划线与驼峰的映射(默认打开)
    cache-enabled: false # 是否开启二级缓存(默认关闭)
  global-config:      # 全局配置
    db-config:
      id-type: auto #id+1自增策略(默认assign_id雪花算法)
      update-strategy: not_empty #null与''都忽略(默认not_null:只忽略null)
      # 下面的配置:将所有的删除语句更改为修改语句
      logic-delete-field: isDelete # 是否删除;全局逻辑删除的实体字段名,字段类型可以是boolean、integer
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

2. 注解用法

以下为整理的常用注解,基本都是标记类表之间的对应关系

@Data
@TableName("tb_user")
public class User {
    //此处配置主键策略优先级 > yml文件
    @TableId(value = "id",type = IdType.AUTO)
    private Long id;
    //与数据库关键字冲突(必加)
    @TableField("`order`")
    private Integer order;
    //is前缀且类型为Boolean(必加)
    @TableField("is_delete")
    private Boolean isDelete;
    //数据表中不存在的(必加)
    @TableField(exist = false)
    private String address;
}

3. 代码生成器

代码生成器根据表名生成mvc各层,实现快速写代码。

  1. 新版idea在tool里找,老版会出现other菜单

image.png

  1. 绑定后,根据需求选择生成,可以自动生成mapper.xml

image.png

4. DB静态工具

Db静态工具跟IService功能几乎一致,主要用来处理依赖冲突问题,在两个service中可以相互依赖

import com.baomidou.mybatisplus.extension.toolkit.Db;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private AddressMapper addressMapper;//不推荐
    @Override
    public void test() {
        //在UserServiceImpl中不推荐注入AddressMapper
        addressMapper.saveAddress(new Address());
        Db.lambdaUpdate(Address.class).update(new Address());//推荐使用Db静态工具
    }
}

5. 枚举处理器

枚举处理器主要用来处理表中数据存储为0,1状态时,通过枚举类对0,1表示内容添加备注

  1. 配置全局枚举处理器
mybatis-plus:
  configuration:
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler #全局枚举处理器

2. 编写枚举类

import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
@Getter
public enum UserStatus {
    STOP_USING(1,"已停用"),
    USING(0,"启用中");
    @EnumValue //表示与数据库交互的值
    private final Integer status;
    @JsonValue //表示返回给前端的值
    private final String desc;
    UserStatus(Integer status, String desc) {
        this.status = status;
        this.desc = desc;
    }
}

3. 查询数据,查询0状态的用户,返回启用中(注:直接打印不会出现想要字符)

@PostMapping("test")
public List<User> test01(){
    return userService.lambdaQuery()
            .eq(User::getStatus,UserStatus.USING).list();
}

6. dto与vo的分页查询

mybatis-plus依旧可以使用常规分页方法,这边介绍mybatis-plus自带的。

  1. 添加分页插件,配置mp的拦截器
@Configuration
public class MybatisConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        // 1.初始化核心插件
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 2.添加分页插件
         PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
         pageInterceptor.setMaxLimit(1000L); // 设置分页上限
                interceptor.addInnerInterceptor(pageInterceptor);
                return interceptor;
    }
}

2. 写两个分页父类,先介绍参数类

@Data
public class PageParam {
    /**
     * 页码
     */
    @TableField(exist = false)
    private Integer pageNum = 1;
    /**
     * 总页数
     */
    @TableField(exist = false)
    private Integer pageSize = 5;
    /**
     * 排序字段
     */
    @TableField(exist = false)
    private String sortBy;
    /**
     * 是否升序
     */
    @TableField(exist = false)
    private Boolean isAsc;

    /**
     * 空排序字段传递排序规则
     * @param items
     * @return
     * @param <T>
     */
    public <T> Page<T> toMpPage(OrderItem ... items){
        // 分页条件
        Page<T> page = Page.of(pageNum, pageSize);
        if(StrUtil.isNotBlank(sortBy)){
            page.addOrder(new OrderItem(sortBy, isAsc));
        }else if(sortBy != null){
            page.addOrder(items);
        }
        return page;
    }

    /**
     * 设定默认值:"更新字段"降序
     * @return
     * @param <T>
     */
    public <T> Page<T> toMpPageDefaultSortByUpdateTime(){
        return toMpPage(new OrderItem("update_time", false));
    }
}

3. 返回数据result类

@Data
public class PageResult<T> {
    /**
     * 总条数
     */
    private Long total;
    /**
     * 总页数
     */
    private Long pages;
    /**
     * 当前页数据
     */
    private List<T> list;

    /**
     * 通过BeanUtil拷贝的形式,实现 dto -> vo
     * @param po
     * @param clazz
     * @return
     * @param <PO>
     * @param <VO>
     */
    public static <PO, VO> PageResult<VO> of(Page<PO> po, Class<VO> clazz){
        PageResult<VO> result = new PageResult<>();
        // 总条数
        result.setTotal(po.getTotal());
        // 总页数
        result.setPages(po.getPages());
        // 当前页数据
        List<PO> records = po.getRecords();
        if(CollUtil.isEmpty(records)){
            result.setList(Collections.emptyList());
            return result;
        }
        // 拷贝VO
        result.setList(BeanUtil.copyToList(records, clazz));
        return result;
    }

    /**
     * 通过传递函数式接口定义规则,实现 dto -> vo
     * @param po
     * @param convertor
     * @return
     * @param <PO>
     * @param <VO>
     */
    public static <PO, VO> PageResult<VO> of(Page<PO> po, Function<PO, VO> convertor){
        PageResult<VO> result = new PageResult<>();
        // 总条数
        result.setTotal(po.getTotal());
        // 总页数
        result.setPages(po.getPages());
        // 当前页数据
        List<PO> records = po.getRecords();
        if(CollUtil.isEmpty(records)){
            result.setList(Collections.emptyList());
            return result;
        }
        // 拷贝VO
        result.setList(records.stream().map(convertor).collect(Collectors.toList()));
        return result;
    }
    
}

4. 案例1

PageResult<UserVo> list = userService.pageSelect(user);
public PageResult<UserVo> pageSelect(User user) {
    //通过传递来的参数点出方法包装为page对象
    Page<User> page = user.toMpPageDefaultSortByUpdateTime();

    //分页+条件查询
    String username = user.getUsername();
    Page<User> pageSelect = lambdaQuery()
            .like(username != null, User::getUsername, username)
            .page(page);

    //一般情况,使用基础的BeanUtil赋值,需要Vo和user字段名一致
    return PageResult.of(pageSelect, UserVo.class);
}

5. 案例2

PageResult<UserVo> list = userService.pageSelect2(user);
@Override
public PageResult<UserVo> pageSelect2(User user) {
    //通过传递来的参数点出方法包装为page对象
    Page<User> page = user.toMpPageDefaultSortByUpdateTime();
    
    //分页+条件查询
    String username = user.getUsername();
    Page<User> pageSelect = lambdaQuery()
            .like(username != null, User::getUsername, username)
            .page(page);

    return PageResult.of(pageSelect,
            //传递匿名内部类 - 处理查询出的数据与Vo的转化
            userTest -> {
                //这里演示拷贝赋值+处理username最后两个字符为**
                UserVo userVo = BeanUtil.copyProperties(userTest, UserVo.class);
                userVo.setTest(userVo.getUsername().substring(0, userVo.getUsername().length() - 2) + "**");
                return userVo;
            });
}