MyBatisPlus学习笔记

embedded/2025/1/20 0:01:48/

To be continue…

文章目录

    • 介绍
    • 快速入门
      • 入门案例
      • 常用注解
      • 常用配置
    • 核心功能
      • 条件构造器
      • 自定义SQL
      • Service接口

介绍

MyBatisPlus只做增强不做改变,引入它不会对现有工程产生影响。只需简单配置,即可快速进行单表CRUD操作,从而节省大量时间。
官方文档:MyBatisPlus

快速入门

入门案例

  1. 引入MyBatisPlus依赖
    mybatis-plus-boot-starter集成了MyBatis和MyBatisPlus的所有功能,因此可以用MyBatisPlus的starter代替MyBatis的starter:
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version>
</dependency>
  1. 定义Mapper
    自定义的Mapper继承MyBatisPlus提供的BaseMapper接口,并指定泛型为对应的实体类:
public interface UserMapper extends BaseMapper<User> {
}

BaseMapper接口中定义了基本的单表增删改查方法

常用注解

MyBatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息。
实体类与数据库表的映射约定为:

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

若实体类不符合约定的命名,需要使用注解进行配置,常用的注解有:

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

@TableId主键类型 idType枚举类型:

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

使用@TableField的常见场景:

  • 成员变量名与数据库字段名不一致
  • 成员变量名以is开头,且是布尔值
  • 成员变量名与数据库关键字冲突,例如@TableField("order") 需要加上反引号
  • 成员变量不是数据库字段,例如@TableField(exist = false)

常用配置

在application.yaml中根据需要添加配置:

mybatis-plus:type-aliases-package: com.itheima.mp.domain.poglobal-config:db-config:id-type: auto

核心功能

条件构造器

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

基于QueryWrapper的查询

@Test
// 查询出名字带o的,存款大于1000元的人的id, username, info, balance
void testQueryWrapper() {// 构建查询条件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
// 更新用户名为jack的用户的余额为2000
void testUpdateByQueryWrapper() {// 要更新的数据User user = new User();user.setBalance(2000);// 更新的条件QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "Jack");// 执行更新userMapper.update(user, wrapper);
}

基于UpdateWrapper的更新

 @Test// 更新id为1, 2, 4的用户的余额扣200void testUpdateWrapper() {List<Long> ids = List.of(1L, 2L, 4L);UpdateWrapper<User> wrapper = new UpdateWrapper<User>().setSql("balance = balance - 200").in("id", ids);userMapper.update(null, wrapper);}

基于LambdaQueryWrapper的查询

@Test
void testLambdaQueryWrapper() {LambdaQueryWrapper<User> wrapper = new QueryWrapper<User>().lambda().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

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

  1. 基于Wrapper构建where条件
@Test
// 将id在指定范围的用户(例如1、2、4)的余额扣减指定值
void testCustomSqlUpdate() {List<Long> ids = List.of(1L, 2L, 4L);int amount = 200;QueryWrapper<User> wrapper = new QueryWrapper<User>().in("id", ids);userMapper.updateBalanceByIds(wrapper, amount);
}
  1. 在mapper方法参数中用Param注解声明wrapper变量名称,必须是ew
void updateBalanceByIds(@Param(Constants.WRAPPER) QueryWrapper<User> wrapper, @Param("amount") int amount);
  1. 自定义SQL,并使用wrapper条件
    可以在方法上使用注解,也可以在xml中写SQL
  <update id="updateBalanceByIds">update tb_userset balance = balance - #{amount} ${ew.customSqlSegment}</update>

Service接口

  1. 自定义Service接口继承IService接口
@Service
public interface IUserService extends IService<User> {
}
  1. 自定义Service实现类,实现自定义接口并继承ServiceImpl类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
  1. 开发基础业务接口
@Api(tags = "用户管理接口")
@RequestMapping("/users")
@RestController
@RequiredArgsConstructor
public class UserController {@Qualifier("IUserService")private final IUserService userService;@ApiOperation("新增用户接口")@PostMappingpublic void saveUser(@RequestBody UserFormDTO userDTO) {// 把DTO拷贝到POUser user = BeanUtil.copyProperties(userDTO, User.class);// 新增userService.save(user);}@ApiOperation("删除用户接口")@DeleteMapping("{id}")public void deleteUserById(@ApiParam("用户id") @PathVariable("id") Long id) {userService.removeById(id);}@ApiOperation("根据id查询用户接口")@GetMapping("{id}")public UserVO queryUserById(@ApiParam("用户id") @PathVariable("id") Long id) {User user = userService.getById(id);return BeanUtil.copyProperties(user, UserVO.class);}@ApiOperation("根据id批量查询用户接口")@GetMappingpublic List<UserVO> queryUserById(@ApiParam("用户id集合") @RequestParam("id")List<Long> ids) {List<User> users = userService.listByIds(ids);return BeanUtil.copyToList(users, UserVO.class);}
}
  1. 开发复杂业务接口
    controller层
    @ApiOperation("扣减用户余额接口")@PutMapping("/{id}/deduction/{money}")public void deductMoneyById(@ApiParam("用户id") @PathVariable("id") Long id,@ApiParam("扣减的金额") @PathVariable("money") Integer money) {userService.deductMoneyById(id, money);}

service层

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Overridepublic void deductMoneyById(Long id, Integer money) {User user = getById(id);if (user == null || user.getStatus() == 2) {throw new RuntimeException("用户状态异常!");}if (user.getBalance() < money) {throw new RuntimeException("用户余额不足!");}baseMapper.deductMoneyById(id, money);}
}

mapper层

@Update("update tb_user set balance = balance - #{money} where id = #{id}")
void deductMoneyById(@Param("id") Long id, @Param("money") Integer money);

启动项目,打开swagger页面调试接口
http://localhost:8080/doc.html
在这里插入图片描述


http://www.ppmy.cn/embedded/155334.html

相关文章

windows 极速安装 Linux (Ubuntu)-- 无需虚拟机

1. 安装 WSL 和 Ubuntu 打开命令行&#xff0c;执行 WSL --install -d ubuntu若报错&#xff0c;则先执行 WSL --update2. 重启电脑 因安装了子系统&#xff0c;需重启电脑才生效 3. 配置 Ubuntu 的账号密码 打开 Ubuntu 的命令行 按提示&#xff0c;输入账号&#xff0c;密…

深入浅出 Go语言并发安全字典 sync.Map:原理、使用与优化

深入浅出 Go语言并发安全字典 sync.Map:原理、使用与优化 背景介绍 Go语言作为一种高效的并发编程语言,其标准库中提供了丰富的并发工具,如sync.WaitGroup、sync.Mutex等。然而,在实际开发中,我们经常需要在多个goroutine之间共享数据,这就涉及到并发安全的问题。传统的…

UDP报文格式

UDP是传输层的一个重要协议&#xff0c;他的特性有面向数据报、无连接、不可靠传输、全双工。 下面是UDP报文格式&#xff1a; 1&#xff0c;报头 UDP的报头长度位8个字节&#xff0c;包含源端口、目的端口、长度和校验和&#xff0c;其中每个属性均为两个字节。报头格式为二…

蓝桥杯2020年国赛C/C++C组第7题 重复字符串(思维与贪心)

解题思路&#xff1a;首先明确&#xff0c;若能将S变为一个K次字符串&#xff0c;那么它的长度应该是K的倍数&#xff0c;如果不是&#xff0c;那么就无法将S变为一个K次字符串&#xff0c;直接按题目要求输出-1即可&#xff0c;如果是&#xff0c;就开始遍历(S/K)长度的字符串…

分布式项目新选择:Dubbo搭建方案

在当今的数字化时代&#xff0c;构建高性能、可扩展的分布式系统已成为众多企业应对业务增长和技术挑战的关键。Dubbo&#xff0c;作为阿里巴巴开源的一款高性能、轻量级的Java RPC框架&#xff0c;为Java开发者提供了一套完善的分布式服务治理方案。本文将详细介绍如何使用Dub…

SSH config

背景 起因就是我发现大部分人对 SSH 只会基本的 ssh userip 的方式登录服务器&#xff0c;至多再会个配置免密&#xff0c;而对 SSH config 几乎不了解。事实上 SSH 可以灵活批量配置服务器信息&#xff0c;配置跳板等等。本文努力普及一些使用细节&#xff0c;希望有一天大家都…

Linux高级--3.3.1 C++ spdlog 开源异步日志方案

一、基本介绍 spdlog 是由 Gustav S. 在 2015 年开发的一个高性能 C 日志库。开发这个库的主要目的是为了提供一个非常快速、轻量、易于使用的日志工具&#xff0c;特别适合需要高性能、低延迟日志记录的 C 应用程序。&#xff08;由于源码现在比较难下载&#xff0c;我把压缩…

opencv对直方图的计算和绘制

【欢迎关注编码小哥&#xff0c;学习更多实用的编程方法和技巧】 1、直方图的计算 cv::calcHist 是 OpenCV 中用于计算图像直方图的函数。它可以处理多通道图像&#xff0c;并通过指定图像、通道、掩膜、直方图大小和范围等参数来生成直方图。 函数原型 void cv::calcHist(…