SpringCloud——MybatisPlus

发布于:2025-05-24 ⋅ 阅读:(18) ⋅ 点赞:(0)

一、快速入门

1.引入相关依赖

2.定义Mapper接口并继承BaseMapper

 二、常见注解

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

2.@TableName:用来指定表名

3.@TableId:用来指定表中的关键字段信息

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

    

三、常见配置

四、条件构造器

注意:

1.QueryWrapper和LambdaQueryWrapper通常用来构建select、delete、update的where条件部分

2.UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用

3.尽量使用LambdaQueryWrapper和LambdaUpdateWrapper,避免硬编码

五、自定义SQL

利用MyBatisPlus的Wrapper来构建复杂的where条件,然后自己定义SQL语句中剩下的部分

1.基于Wrapper构建where条件

2.在mapper方法参数用Param注解声明Wrapper变量名称,必须是ew

3.自定义SQL,并实用Wrapper条件

 六、IService接口

1、继承实现结构

2、Lambda

查询相关操作:

@Override
    public  List<User> complexSearch(String name, Integer status, Integer minBalance, Integer maxBalance) {
       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();

    }

更新相关操作:

@Override
    public void minusMoneyById(Long id, Long money) {
        //通过id查找用户
        User userById = this.getById(id);
        if (userById == null) {
            throw new RuntimeException("扣减失败,用户不存在");
        }
        //判断用户状态
        if (userById.getStatus() == 2) {
            throw new RuntimeException("扣减失败,用户被冻结");
        }
        //判断账户余额
        if (userById.getBalance() == 0 || userById.getBalance() < money) {
            throw new RuntimeException("扣减失败,余额不足");
        }
        long updateBalance = userById.getBalance() - money;
        //baseMapper.minusMoneyById(id, money);
        lambdaUpdate().set(User::getBalance, updateBalance).set(updateBalance==0,User::getStatus,2).eq(User::getId,id).update();
    }

批量新增相关操作:

开启rewriteBatchedStatements=true

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true

3、静态工具

相关依赖:

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

相关代码:

 @Override
    public UserVO selectUserAndAddress(Long id) {
        //根据id查询用户
        UserVO userVO = new UserVO();
        User selectUserById = this.lambdaQuery().eq(User::getId, id).one();
        if (selectUserById == null||selectUserById.getStatus() == 2) {
            throw new RuntimeException("用户状态异常");
        }
        BeanUtils.copyProperties(selectUserById, userVO);
        //根据用户id查询地址
        List<Address> adressList = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();
        if (adressList != null && adressList.size() > 0) {
            ArrayList<AddressVO> addressVOS = new ArrayList<>();
            for (Address address : adressList) {
                AddressVO addressVO = new AddressVO();
                BeanUtils.copyProperties(address, addressVO);
                addressVOS.add(addressVO);
            }
            userVO.setAddresses(addressVOS);
        }

        return userVO;
    }

4、逻辑删除

逻辑删除就是基于代码逻辑模拟删除效果,但并不会真正删除数据

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

5、枚举处理器

mybatisPlus提供了一个处理枚举的类型转换器,可以帮我们把枚举类型与数据库类型自动转换。

定义枚举:

package com.itheima.mp.enums;

import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;

public enum UserStatus {
    Normal(1,"正常"),
    FROZON(2,"冻结"),
    ;
    @EnumValue
    private final int value;
    @JsonValue
    private final String desc;

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

配置枚举处理器:

mybatis-plus:
  configuration:
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler

6、Json处理器

将数据库中字符串的数据转换为实体对象

定义实体类:

package com.itheima.mp.domain.po;

import lombok.Data;

@Data
public class UserInfo {
    private Integer age;
    private String intro;
    private String gender;
}

使用处理器:

package com.itheima.mp.domain.po;

import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.itheima.mp.enums.UserStatus;
import lombok.Data;

import java.time.LocalDateTime;

@Data
// @TableName(value = "myuser")
@TableName( autoResultMap = true)
public class User {

    /**
     * 用户id
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 注册手机号
     */
    private String phone;

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

    /**
     * 使用状态(1正常 2冻结)
     */
    //@TableField(value = "status")
    private UserStatus status;

    /**
     * 账户余额
     */
    //@TableField(exist = false)
    private Integer balance;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;
}

7、分页插件

配置插件:

package com.itheima.mp.domain.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        // 初始化核心插件
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

}

分页API:

 @Test
    void testPage(){
        Page<User> myPage = Page.of(3, 2);
        Page<User> pageFromDatabase = userServiceImpl.page(myPage);
        for (User user : pageFromDatabase.getRecords()) {
            System.out.println(user);
        }
    }

分页参数实体:

package com.itheima.mp.domain.query;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(description = "分页查询相关实体")
public class PageQuery {
    @ApiModelProperty("页码")
    private Integer pageNo=1;
    @ApiModelProperty("页码")
    private Integer pageSize=5;
    @ApiModelProperty("牌序字段")
    private String sortBy;
    @ApiModelProperty("是否升序")
    private Boolean isAsc;

    public <T> Page<T> toMpPage(OrderItem ... orderItems) {
        //分页条件
        Page<T> page = Page.of(pageNo, pageSize);

        //排序依靠、排序方式
        //排序字段不为空
        if  (StrUtil.isNotBlank(sortBy)) {
            page.addOrder(new OrderItem().setColumn(sortBy).setAsc(isAsc));
        }else {
            page.addOrder(orderItems);
        }
        return page;
    }

    public <T> Page<T> toMpPageDefaultOrderByCreateTime(){
        return toMpPage(new OrderItem().setColumn("create_time").setAsc(false));
    }

    public <T> Page<T> toMpPageDefaultOrderByUpdateTime(){
        return toMpPage(new OrderItem().setColumn("update_time").setAsc(false));
    }

    public <T> Page<T> toMpPage(String sortBy, Boolean isAsc) {
        return toMpPage(new OrderItem().setColumn(sortBy).setAsc(isAsc));
    }
}

实体类继承分页参数实体:

package com.itheima.mp.domain.query;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(description = "用户查询条件实体")
public class UserQuery extends PageQuery {
    @ApiModelProperty("用户名关键字")
    private String name;
    @ApiModelProperty("用户状态:1-正常,2-冻结")
    private Integer status;
    @ApiModelProperty("余额最小值")
    private Integer minBalance;
    @ApiModelProperty("余额最大值")
    private Integer maxBalance;


}

统一响应返回实体:

package com.itheima.mp.domain.dto;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageDTO<V> {
    private Long total;
    private Long pages;
    private List<V> list;

    /**
     * 返回空分页结果
     * @param p MybatisPlus的分页结果
     * @param <V> 目标VO类型
     * @param <P> 原始PO类型
     * @return VO的分页对象
     */
    public static <V, P> PageDTO<V> empty(Page<P> p){
        return new PageDTO<>(p.getTotal(), p.getPages(), Collections.emptyList());
    }

    /**
     * 将MybatisPlus分页结果转为 VO分页结果
     * @param p MybatisPlus的分页结果
     * @param voClass 目标VO类型的字节码
     * @param <V> 目标VO类型
     * @param <P> 原始PO类型
     * @return VO的分页对象
     */
    public static <V, P> PageDTO<V> of(Page<P> p, Class<V> voClass) {
        // 1.非空校验
        List<P> records = p.getRecords();
        if (records == null || records.size() <= 0) {
            // 无数据,返回空结果
            return empty(p);
        }
        // 2.数据转换
        List<V> vos = BeanUtil.copyToList(records, voClass);
        // 3.封装返回
        return new PageDTO<>(p.getTotal(), p.getPages(), vos);
    }

    /**
     * 将MybatisPlus分页结果转为 VO分页结果,允许用户自定义PO到VO的转换方式
     * @param p MybatisPlus的分页结果
     * @param convertor PO到VO的转换函数
     * @param <V> 目标VO类型
     * @param <P> 原始PO类型
     * @return VO的分页对象
     */
    public static <V, P> PageDTO<V> of(Page<P> p, Function<P, V> convertor) {
        // 1.非空校验
        List<P> records = p.getRecords();
        if (records == null || records.size() <= 0) {
            // 无数据,返回空结果
            return empty(p);
        }
        // 2.数据转换
        List<V> vos = records.stream().map(convertor).collect(Collectors.toList());
        // 3.封装返回
        return new PageDTO<>(p.getTotal(), p.getPages(), vos);
    }
}


网站公告

今日签到

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