当前位置: 首页 > news >正文

MybatisPlus速成

MybatisPlus快速入门

  • 快速入门
    • 入门案例
    • 常见注解
    • 常见配置
  • 核心功能
    • 条件构造器
    • 自定义SQL
    • Service接口
  • 扩展功能
    • 代码生成
    • 静态工具
    • 逻辑删除
    • 枚举处理器
    • JSON处理器
  • 插件功能
    • 分页插件
    • 通用分页实体

参考文档
mybatis-plus参考文档
全部资料链接
讲义

快速入门

入门案例

在这里插入图片描述在这里插入图片描述

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

在这里插入图片描述

@Mapper
public interface UserMapper extends BaseMapper<User> { // 记得指定泛型为你操作的实体类的类型
}

在这里插入图片描述

常见注解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

常见配置

在这里插入图片描述
在这里插入图片描述

核心功能

条件构造器

在这里插入图片描述
在这里插入图片描述

 @Testvoid testQueryWrapper(){// 1.构建查询条件QueryWrapper<User> wrapper = new QueryWrapper<User>().select("id", "username", "info", "balance").like("username", "o").ge("balance", 1000);// 2.查询List<User> users = userMapper.selectList(wrapper);//3. 遍历打印users.forEach(System.out::println);}@Testvoid testUpdateByQueryWrapper(){// 1. 要更新的数据User user = new User();user.setBalance(2000);// 2. 更新的操作QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username","jack");// 3. 执行更新userMapper.update(user,wrapper);}

在这里插入图片描述

@Testvoid testUpdateWrapper(){List<Long> ids = Arrays.asList(1L, 2L, 3L);UpdateWrapper<User> wrapper = new UpdateWrapper<User>().setSql("balance = balance - 200").in("id",ids);userMapper.update(null,wrapper);}
@Testvoid testLambdaQueryWrapper(){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);}

在这里插入图片描述

自定义SQL

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Service接口

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们的自定义接口UserService需要去继承IService接口,我们的实现类UserServiceImpl也要继承他的实现类ServiceImpl
在这里插入图片描述

package com.itheima.mp.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.mp.domain.po.User;public interface IUserService extends IService<User> {
}
package com.itheima.mp.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.mapper.UserMapper;
import com.itheima.mp.service.IUserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {// 泛型中要指定mapper的类型和实体类的类型
}
package com.itheima.mp.service;import com.itheima.mp.domain.po.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;import static org.junit.jupiter.api.Assertions.*;@SpringBootTest
class IUserServiceTest {@Autowiredprivate IUserService userService;@Testvoid testSaveUser(){User user = new User();
//        user.setId(5L);user.setUsername("Lilei");user.setPassword("123");user.setPhone("18688990011");user.setBalance(200);user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");user.setCreateTime(LocalDateTime.now());user.setUpdateTime(LocalDateTime.now());userService.save(user);}@Testvoid testQuery(){List<User> users = userService.listByIds(Arrays.asList(1L, 2L, 3L));users.forEach(System.out::println);}
}

在这里插入图片描述

package com.itheima.mp.controller;import cn.hutool.core.bean.BeanUtil;
import com.itheima.mp.domain.dto.UserFormDTO;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.query.UserQuery;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.service.IUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@Api(tags = "用户管理接口")
@RequestMapping("/users")
@RestController
@RequiredArgsConstructor
public class UserController {// final搭配lombok的RequiredArgsConstructor注解// 实现根据需要自动注入,不需要注入的不加lombok注解就行了private final IUserService userService;@ApiOperation("新增用户接口")@PostMappingpublic void saveUser(@RequestBody UserFormDTO userDto){// 1. 把DTO拷贝到POUser user = BeanUtil.copyProperties(userDto, User.class);// 2. 新增userService.save(user);}@ApiOperation("删除用户接口")@DeleteMapping("{id}")public void deleteUserById(@ApiParam("用户id") @PathVariable("id") Long id){userService.removeById(id);}@ApiOperation("根据id查询用户")@GetMapping("{id}")public UserVO getUserById(@ApiParam("用户id") @PathVariable("id") Long id){User user = userService.getById(id);return BeanUtil.copyProperties(user,UserVO.class);}@ApiOperation("根据id批量查询用户")@GetMappingpublic List<UserVO> getUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){List<User> users = userService.listByIds(ids);return BeanUtil.copyToList(users,UserVO.class);}@ApiOperation("扣减用户余额接口")@DeleteMapping("{id}/deduction/{money}")public void deductMoneyById(@ApiParam("用户id") @PathVariable("id") Long id,@ApiParam("扣减的金额") @PathVariable("money") Integer money){userService.deductBalance(id, money);}
}

在这里插入图片描述
controller层

@ApiOperation("根据复杂条件查询用户")@GetMapping("/list")public List<UserVO> queryUsers(UserQuery query){// 1. 查询用户POList<User> users = userService.queryUsers(query.getName(),query.getStatus(),query.getMinBalance(),query.getMaxBalance());// 2. 把PO拷贝到VOreturn BeanUtil.copyToList(users, UserVO.class);}

service层

@Overridepublic List<User> queryUsers(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@Transactionalpublic void deductBalance(Long id, Integer money) {// 1.  查询用户User user = getById(id);    // 我们继承了ServiceImpl,爸爸的就是我的,已经有UserService了,不用注入,this一下看看哦// 2. 校验用户状态if(user==null || user.getStatus() == 2 ){throw new RuntimeException("用户状态异常");}// 3. 校验余额是否充足if(user.getBalance() < money){throw new RuntimeException("用户余额不足!");}// 4. 扣减余额 update user set balance  = balance - ?
//        baseMapper.deductBalance(id,money);int remainBalance = user.getBalance() - money;lambdaUpdate().set(User::getBalance,remainBalance).set(remainBalance == 0,User::getStatus,0).eq(User::getId,id).eq(User::getBalance,user.getBalance())   // 乐观锁.update();  // 一定记得加上update,上面只是在构建sql语句}

在这里插入图片描述

扩展功能

代码生成

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

静态工具

在这里插入图片描述
在这里插入图片描述
根据id查询用户的接口

    @ApiOperation("根据id查询用户")@GetMapping("{id}")public UserVO getUserById(@ApiParam("用户id") @PathVariable("id") Long id){
//        User user = userService.getById(id);
//        return BeanUtil.copyProperties(user,UserVO.class);return userService.queryUserAndAddressById(id);}

实现方法

    @Overridepublic UserVO queryUserAndAddressById(Long id) {// 1. 查询用户User user = getById(id);if(user == null || user.getStatus() == 2){throw new RuntimeException("用户状态异常!");}// 2. 查询地址——使用静态工具List<Address> addresses = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();// 3.封装VO// 3.1转User额PO为VoUserVO userVO = BeanUtil.copyProperties(user, UserVO.class);//3.2 转地址VOif(CollUtil.isNotEmpty(addresses)){userVO.setAddresses(BeanUtil.copyToList(addresses, AddressVO.class));}return userVO;}

根绝id批量查询用户的接口
controller层

    @ApiOperation("根据id批量查询用户")@GetMappingpublic List<UserVO> getUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){
//        List<User> users = userService.listByIds(ids);
//        return BeanUtil.copyToList(users,UserVO.class);return userService.queryUserAndAddressByIds(ids);}

实现

@Overridepublic List<UserVO> queryUserAndAddressByIds(List<Long> ids) {// 1. 查询用户List<User> users = listByIds(ids);if(CollUtil.isEmpty(users)){return Collections.emptyList();}// 2.查询地址// 2.1 获取用户id集合List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());// 2.2 根据用户id查询地址List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();// 2.3 转换地址VOList<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);// 2.4 用户地址集合分组处理,相同的用户放入一个集合(组)中Map<Long, List<AddressVO>> addressMap = new HashMap<>(0);if(CollUtil.isNotEmpty(addressVOList)){addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));}// 3. 转换VO返回ArrayList<UserVO> list = new ArrayList<>(users.size());for (User user : users) {// 3.1. 转换User的PO为VOUserVO vo = BeanUtil.copyProperties(user, UserVO.class);// 3.2 转换地址VOvo.setAddresses(addressMap.get(user.getId()));list.add(vo);}return list;}

逻辑删除

在这里插入图片描述
在这里插入图片描述

枚举处理器

就是Java中的枚举类型和数据库中的int类型的转换的问题
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.itheima.mp.enums;import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;@Getter
public enum UserStatus {NORML(1,"正常"),FROZEN(2,"冻结"),;@EnumValueprivate final int value;@JsonValue  // 前端默认返回枚举项的名字,不友好,设置返回desc(由spring控制)private final String desc;UserStatus(int value, String desc){this.value = value;this.desc = desc;}
}

JSON处理器

实现Java中的对象和数据库中的json格式数据的映射
在这里插入图片描述

package com.itheima.mp.domain.po;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor(staticName = "of")
public class UserInfo {private Integer age;private String intro;private String gender;
}

在这里插入图片描述

package com.itheima.mp.domain.po;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.itheima.mp.enums.UserStatus;
import lombok.Data;import java.time.LocalDateTime;@Data
@TableName(value = "user", autoResultMap = true)
public class User {/*** 用户id*/@TableId(type = IdType.AUTO)private Long id;/*** 用户名*/private String username;/*** 密码*/private String password;/*** 注册手机号*/private String phone;/*** 详细信息*/@TableField(typeHandler = JacksonTypeHandler.class)private UserInfo info;/*** 使用状态(1正常 2冻结)*/private UserStatus status;/*** 账户余额*/private Integer balance;/*** 创建时间*/private LocalDateTime createTime;/*** 更新时间*/private LocalDateTime updateTime;
}
package com.itheima.mp.domain.vo;import com.itheima.mp.domain.po.UserInfo;
import com.itheima.mp.enums.UserStatus;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import java.util.List;@Data
@ApiModel(description = "用户VO实体")
public class UserVO {@ApiModelProperty("用户id")private Long id;@ApiModelProperty("用户名")private String username;@ApiModelProperty("详细信息")private UserInfo info;@ApiModelProperty("使用状态(1正常 2冻结)")private UserStatus status;@ApiModelProperty("账户余额")private Integer balance;@ApiModelProperty("用户的收货地址")private List<AddressVO> addresses;
}

插件功能

在这里插入图片描述

在这里插入图片描述

分页插件

在这里插入图片描述

package com.itheima.mp.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 {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();//创建分页插件PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);paginationInnerInterceptor.setMaxLimit(1000L);// 添加分页插件interceptor.addInnerInterceptor(paginationInnerInterceptor);return interceptor;}}

在这里插入图片描述
在这里插入图片描述

@Testvoid testPageQuery(){int pageNo = 1, pageSize = 2;// 准备分页条件// 1.1 分页条件Page page = Page.of(pageNo, pageSize);// 1.2 排序条件page.addOrder(new OrderItem("balance", true));page.addOrder(new OrderItem("id",true));// 2. 分页查询Page<User> p = userService.page(page);// 3. 解析// 2.总条数System.out.println("total = " + p.getTotal());// 3.总页数System.out.println("pages = " + p.getPages());// 4.数据List<User> records = p.getRecords();records.forEach(System.out::println);}

通用分页实体

在这里插入图片描述
在这里插入图片描述

package com.itheima.mp.domain.query;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;@Data
@ApiModel(description = "分页查询实体")
public class PageQuery {@ApiModelProperty("页码")private Long pageNo;@ApiModelProperty("页码")private Long pageSize;@ApiModelProperty("排序字段")private String sortBy;@ApiModelProperty("是否升序")private Boolean isAsc;
}
package com.itheima.mp.domain.query;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;@EqualsAndHashCode(callSuper = true)
@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;
}

controller层

  @ApiOperation("根据分页查询用户接口")@GetMapping("/page")public PageDto<UserVO> queryUsersPage(UserQuery query){return userService.queryUsersPage(query);}

service层

@Overridepublic PageDto<UserVO> queryUsersPage(UserQuery query) {String name = query.getName();Integer status = query.getStatus();// 构建分页条件// 1.1分页条件Page<User> page = Page.of(query.getPageNo(), query.getPageSize());// 1.2 排序条件if(StrUtil.isNotBlank(query.getSortBy())){// 不为空page.addOrder(new OrderItem(query.getSortBy(),query.getIsAsc()));}else{// 为空,默认按照更新时间排序page.addOrder(new OrderItem("update_time",false));}// 2. 分页查询Page<User> p = lambdaQuery().like(name != null, User::getUsername, name).eq(status != null, User::getStatus,status).page(page);// 封装VO结果PageDto<UserVO> dto = new PageDto<>();// 3.1 总条数dto.setTotal(p.getTotal());// 3.2 总页数dto.setPages(p.getPages());// 3.3 当前页数据List<User> records = p.getRecords();if(CollUtil.isEmpty(records)){dto.setList(Collections.emptyList());return dto;}// 3.4 拷贝user的VOList<UserVO> vos = BeanUtil.copyToList(records, UserVO.class);dto.setList(vos);// 4返回return dto;}

在这里插入图片描述

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 com.itheima.mp.domain.po.User;
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 = true;public  <T> Page<T> toMpPage(OrderItem ... items){// 1.1分页条件Page<T> page = Page.of(pageNo, pageSize);// 1.2 排序条件if(StrUtil.isNotBlank(sortBy)){// 不为空page.addOrder(new OrderItem(sortBy,isAsc));}else if(items != null){// 为空,默认排序page.addOrder(items);}return page;}public <T> Page<T> toMpPage(String defaultSortBy, Boolean defaultAsc){return toMpPage(new OrderItem(defaultSortBy,defaultAsc));}public <T> Page<T> toMpPageDefaultSortByCreateTime(){return toMpPage(new OrderItem("create_time",false));}public <T> Page<T> toMpPageDefaultSortByUpdateTime(){return toMpPage(new OrderItem("update_time",false));}}
package com.itheima.mp.domain.dto;import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;@Data
@ApiModel(description = "分页结果")
public class PageDTO<T> {@ApiModelProperty("总条数")private Long total;@ApiModelProperty("总页数")private Long pages;@ApiModelProperty("集合")private List<T> list;public static <PO,VO> PageDTO<VO> of(Page<PO> p, Function<PO,VO> convertor){PageDTO<VO> dto = new PageDTO<>();// 3.1 总条数dto.setTotal(p.getTotal());// 3.2 总页数dto.setPages(p.getPages());// 3.3 当前页数据List<PO> records = p.getRecords();if(CollUtil.isEmpty(records)){dto.setList(Collections.emptyList());return dto;}// 3.4 拷贝user的VOdto.setList(records.stream().map(convertor).collect(Collectors.toList()));// 4返回return dto;}
}

封装完成后,分页查询的实现就更简洁了

@Overridepublic PageDTO<UserVO> queryUsersPage(UserQuery query) {String name = query.getName();Integer status = query.getStatus();// 构建分页条件Page<User> page = query.toMpPageDefaultSortByUpdateTime();// 2. 分页查询Page<User> p = lambdaQuery().like(name != null, User::getUsername, name).eq(status != null, User::getStatus,status).page(page);// 3.封装VO结果PageDTO<UserVO> dto = new PageDTO<>();return PageDTO.of(p,user->{// 1. 拷贝基础属性UserVO vo = BeanUtil.copyProperties(user, UserVO.class);// 2. 处理特殊逻辑vo.setUsername(vo.getUsername().substring(0, vo.getUsername().length() - 2) + "**");return vo;});}
http://www.lryc.cn/news/329581.html

相关文章:

  • 【Django开发】0到1美多商城项目md教程第4篇:图形验证码,1. 图形验证码接口设计【附代码文档】
  • 八股 -- C#
  • 科创新格局·共赢双循环“2024上海智能科技与创新展览会”
  • Chatopera 云服务的智能问答引擎实现原理,如何融合 #聊天机器人 技术 #Chatbot #AI #NLP
  • 基于CNN-RNN的动态手势识别系统实现与解析
  • 华为鲲鹏认证考试内容有哪些
  • Gitlab CI---could not read username for xxx: no such device or address
  • 三个AI创业方向各有特点和市场潜力
  • C语言学习笔记二
  • Sublime Text4 4169 安装激活【亲测可用】
  • 【数据结构与算法初阶(c语言)】插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序、归并排序、计数排序-全梳理(万字详解,干货满满,建议三连收藏)
  • [蓝桥杯 2019 省赛 AB] 完全二叉树的权值
  • 亮数据Bright Data,引领高效数据采集新体验
  • C#学习笔记
  • 【A-006】基于SSH的新闻发布系统(含论文)
  • c语言-static
  • zuul的性能调优
  • C++中的动态内存管理
  • es6的核心语法
  • Unity | 射线检测及EventSystem总结
  • 职业经验 2024 年测试求职手册
  • Spring Boot与Redis深度整合:实战指南
  • 微服务(基础篇-006-Docker安装-CentOS7)
  • 前端-css-01
  • Java学习36-Java 多线程安全:懒汉式和饿汉式
  • sql常用之CASE WHEN THEN
  • 【PduR路由】IPduM模块详细介绍
  • 【MySQL】6.MySQL主从复制和读写分离
  • Lucene及概念介绍
  • 密码算法概论