重生之我在暑假学习微服务第一天《MybatisPlus-上篇》

 

本系列参考黑马程序员微服务课程,有兴趣的可以去查看相关视频,本系列内容采用渐进式方式讲解微服务核心概念与实践方法,每日更新确保知识点的连贯性。通过系统化学习路径帮助开发者掌握分布式系统构建的关键技术。读者可通过平台订阅功能获取最新章节推送,及时了解服务拆分、容器化部署、服务网格等前沿技术动态。

  •  个人主页:VON
  • 文章所属专栏:微服务
  • 系列文章链接:暂无
  • 时间:每天12点准时更新

目录

前言

一、MyBatis-Plus 与 MyBatis 的区别

功能增强

开发效率

扩展性

适用场景

示例对比

二、引入Mybits-Plus

1.下载依赖

 2.继承BaseMapper​编辑

 3、修改代码

4.测试 

插入

查询 (单条数据)

 查询 (多条数据)

更新数据 

​编辑 删除数据

三、常见注解

@TableName

 示例:

@TableId

示例:

@TableField

常见的配置

 四、条件构造器

1、基于QueryWrapper查询

 2、基于UpdateWrapper更新

 五、自定义SQL

六、Service接口

1、基础用法

2、实现简单业务接口

3、实现复杂业务接口

4.开始测试

(1)增加用户信息

(2)查询用户信息

(3)批量查询用户信息

(4)扣减用户余额

(5)删除用户信息

 (6)根据Lambda查询用户信息

​编辑

 (7)IService批量新增

结语


前言

蝉鸣撕心裂肺时,VON从冷汗里弹起来。​

泛黄的墙壁,潦草的名字,2030 年 7 月 15 日的日历 —— 这不是他被总监骂 "连 MybatisPlus 都不会" 的会议室。​

他重生回了高考后的暑假。​

前世因荒废假期,他在大学跟不上课程,工作后写几百行冗余 SQL 被嘲笑,看同事玩转微服务自己却连基础都摸不透。那些羞辱像针一样扎着。​

班长的消息弹出来:"学长推荐了入门微服务的资料,从 MybatisPlus 开始。"​

VON盯着那行字,心脏狂跳。前世他就是嫌难,把整个夏天耗在了游戏里。​

"这次不能再错过。"​

他抓起手机,点开前世屏蔽的技术公众号,目光落在《MybatisPlus 基础入门》上。窗外的蝉鸣突然温顺了,阳光在崭新的教程封面上,映出他眼里的光。​

重生第一天,就从搞懂 MybatisPlus 开始。

一、MyBatis-Plus 与 MyBatis 的区别

Mybits-Plus官网

Mybits官网

MyBatis-Plus(简称 MP)是基于 MyBatis 的增强工具,旨在简化开发并提高效率,核心区别如下:


功能增强

MyBatis-Plus 在 MyBatis 基础上提供了大量开箱即用的功能:

  • 自动化 CRUD:内置通用 Mapper 和 Service,无需手动编写基础 SQL。
  • 条件构造器:通过 QueryWrapperUpdateWrapper 等实现动态 SQL 拼接。
  • 代码生成器:自动生成实体类、Mapper、Service 等代码。
  • 分页插件:内置分页支持,无需额外配置。

开发效率

MyBatis 需要手动编写 SQL 和结果映射,而 MyBatis-Plus 通过约定优于配置减少冗余代码:

  • 默认映射实体类与数据库表字段(支持驼峰转换)。
  • 提供 Lambda 表达式写法,避免硬编码字段名。

扩展性

  • MyBatis-Plus 完全兼容原生 MyBatis,可混合使用。
  • 支持自定义全局操作(如逻辑删除、自动填充字段)。

适用场景

  • MyBatis:需高度定制复杂 SQL 或已有成熟 MyBatis 项目。
  • MyBatis-Plus:快速开发常规业务(如后台管理系统),减少样板代码。

示例对比

MyBatis 示例

MyBatis-Plus 等价操作

二、引入Mybits-Plus

1.下载依赖

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

 2.继承BaseMapper

 3、修改代码

原来代码👇

 将原来代码中的语句直接删除

Mapper也同理

 修改测试类中的方法即可,根据提示直接回车即可

4.测试 

插入

 插入成功

查询 (单条数据)

 查询 (多条数据)

更新数据 

 删除数据

 由此可见增删改查功能全部正常,目前的代码极大的简化了原本的代码

三、常见注解

@TableName

用于指定实体类对应的数据库表名。当实体类名与数据库表名不一致时,使用该注解进行映射。

@TableName("user_info")
public class User {
    // 类字段
}

 示例:

@TableId

用于标识主键字段,并可以指定主键生成策略。常见的属性包括value(数据库主键字段名)和type(主键生成策略)。

@TableId(value = "id", type = IdType.AUTO)
private Long id;

主键生成策略(IdType)常见选项:

  • AUTO:数据库自增
  • INPUT:手动输入
  • ASSIGN_ID:雪花算法生成ID
  • ASSIGN_UUID:生成UUID

示例:

这里测试一下自增

@TableField

用于标注非主键字段,解决字段名与数据库列名不一致的问题,或标识非表字段(如 transient 字段)。

@TableField("user_name")
private String name;

@TableField(exist = false)
private String tempData;

常见属性:

  • value:数据库字段名(默认与属性名一致时可不填)
  • exist:是否为数据库字段(默认为true
  • fill:字段自动填充策略(如FieldFill.INSERT插入时填充)

注:当exist设置为false时该字段不显示

注:在数据库设计或查询中,偶尔会遇到表名与数据库保留关键字相同的情况。这可能导致语法错误或执行失败。以下是几种常见的解决方法:

使用引号或方括号包裹表名 不同数据库系统对保留关键字的处理方式不同。MySQL使用反引号(`),SQL Server使用方括号([]),PostgreSQL和Oracle使用双引号("")。例如:

-- MySQL
SELECT * FROM `order`;

-- SQL Server
SELECT * FROM [order];

-- PostgreSQL/Oracle
SELECT * FROM "order";

修改表名 避免使用数据库保留关键字作为表名是最佳实践。可以通过添加前缀或后缀来修改表名,例如tbl_orderorders

使用别名 在查询中为表指定别名可以避免直接使用关键字。例如:

SELECT o.* FROM `order` AS o WHERE o.id = 1;

数据库保留关键字列表 不同数据库系统的保留关键字各不相同。

常见的配置

mybitis-plus:
  # 配置Mapper XML文件的位置
  mapper-locations: classpath*:mapper/*.xml
  configuration:
    # 开启下划线转驼峰命名映射
    map-underscore-to-camel-case: true
    # 指定MyBatis日志实现方式,输出到控制台
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 关闭二级缓存
    cache-enabled: false
  global-config:
    db-config:
      # 主键生成策略:自动递增
      id-type: auto
      # 逻辑删除字段名
      logic-delete-field: is_deleted
      # 逻辑删除值(标记为已删除)
      logic-delete-value: 1
      # 逻辑未删除值(标记为未删除)
      logic-not-delete-value: 0
      # 逻辑删除列名
      logic-delete-column: is_deleted
      # 逻辑删除类型为列模式
      logic-delete-type: COLUMN
      # 数据库类型
      db-type: mysql
      # 表前缀
      table-prefix: tbl_
      # 字段策略:智能判断非空字段
      field-strategy: smart
      # 更新策略:智能判断非空字段
      update-strategy: smart
      # 插入策略:智能判断非空字段
      insert-strategy: smart

一般配置成这样就可以了 

想要了解更多的可以看官方文档👇

文章开头部分已经引入了文档官网

 四、条件构造器

1、基于QueryWrapper查询

//条件构造器测试案例
    @Test
    void textOne1(){
        //查询名字带o,并且存款大于1000的用户
        List<User> users = userMapper.selectList(new QueryWrapper<User>().like("username", "o").gt("balance", 1000));
        users.forEach(System.out::println);
    }

    @Test
    void textOne2(){
        //将张三存款改为10000
        User user = new User();
        user.setBalance(10000);
        QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "张a三");
        userMapper.update(user, wrapper);
    }

 可见查询到了一条符合的语句

 可见余额已经修改为10000了

 2、基于UpdateWrapper更新

@Test
    void textTwo1(){
        //基于UpdateWrapper更新id为1,2,3的用户余额减500
        UpdateWrapper<User> wrapper = new UpdateWrapper<User>().in("id", 1, 2, 3).setSql("balance = balance - 500");
        userMapper.update(null, wrapper);
    }

更新前的数据如下

 更新后的数据

 五、自定义SQL

这种写法是 “用分层设计让代码更干净,用动态条件适配变化,用 XML 管好 SQL ,用测试保障质量” ,本质是为了让数据库操作的 “开发更灵活、维护更简单、协作更顺畅、质量更可控”

测试用例驱动(功能触发层)
编写 textCustomSqlQuery 测试方法,先定义更新参数(用户 ID 列表 ids、扣除金额 amount ),再用 QueryWrapper 构建 id IN (1,2,3) 的条件,最后调用 userMapper.updateBalanceByIds ,作为功能入口触发数据库操作。

Mapper 接口约定(方法声明层)
在 UserMapper 接口中定义 updateBalanceByIds 方法,通过 @Param 明确入参(条件 wrapper、金额 amount ),约定参数传递规则,作为 XML 映射 SQL 的 “调用声明”。

XML 映射执行(SQL 实现层)
XML 中通过 <update id="updateBalanceByIds"> 绑定接口方法,编写 SQL :UPDATE tb_user SET balance = balance - #{amount} ${ew.customSqlSegment} ,既用 #{amount} 安全传参,又通过 ${ew.customSqlSegment} 拼接条件,最终在数据库执行 “按 ID 批量扣余额” 的更新。

测试用例负责场景触发,Mapper 接口定义调用契约,XML 映射实现具体 SQL ,协同完成数据库更新逻辑。

六、Service接口

1、基础用法

只需继承一下接口即可

这里做一个简单的测试

 直接就可以对数据库中的数据进行修改

2、实现简单业务接口

 添加配置文件

<!--swagger-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
            <version>4.1.0</version>
        </dependency>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

修改yaml文件,加入以下代码

knife4j:
  enable: true
  openapi:
    group:
      default:
        group-name: default
        api-rule: package
        api-rule-resources:
          - com.itheima.mp.controller

添加UserVO和UserFormDTO两个实体类

开始写Controller代码

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.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.web.bind.annotation.*;

import java.util.List;

@Api(tags = "用户管理相关接口")
@RequestMapping("/users")
@RestController
@RequiredArgsConstructor
public class UserController {

    private final IUserService userService;

    @ApiOperation("新增用户")
    @PostMapping
    public void saveUser(@RequestBody UserFormDTO userDTO){
        //1.把DTO转换成PO
        User user = BeanUtil.copyProperties(userDTO,User.class);
        //2.调用service完成新增
        userService.save(user);
    }

    @ApiOperation("删除用户")
    @DeleteMapping("/{id}")
    public void deleteUserById(@ApiParam("用户id") @PathVariable("id") Long id){
        userService.removeById(id);
    }

    @ApiOperation("查询用户")
    @GetMapping("/{id}")
    public UserVO queryUserById(@ApiParam("用户id") @PathVariable("id") Long id){
        //1.查询用户PO
        User user = userService.getById(id);
        //2.把PO转换成VO
        return BeanUtil.copyProperties(user,UserVO.class);
    }

    @ApiOperation("批量查询用户")
    @GetMapping("/{id}")
    public List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){
        //1.查询用户PO
        List<User> users = userService.listByIds(ids);
        //2.把PO转换成VO
        return BeanUtil.copyToList(users,UserVO.class);
    }
}

3、实现复杂业务接口

这里的请求方式是PUT请求,这里写错了,留意一下

最后一行的id应该是id的,这里写成ew了🤡🤡🤡

4.开始测试

这里用的是Apifox

(1)增加用户信息

发送post请求

 成功插入数据

(2)查询用户信息

注意下这里是GET请求

(3)批量查询用户信息

(4)扣减用户余额

这里是PUT请求

这里扣减id为5的用户

 余额变成9000了

(5)删除用户信息

删除id为7的用户

可以看到id为7的用户被删除了 

以上的测试后端也都响应回来了 

 (6)根据Lambda查询用户信息

先创建一个实体类,参数多的情况下不建议一个一个输入

controller和service层代码

 注意下这里的请求路径为了和上文区分改成了list

看下实体类中的参数,都可以进行查询

这里的状态码全为1,所以没有查询到状态码为2的。 

细心的话不难发现2号余额为负数

 先将他的余额设置成100,然后在减余额

这里的逻辑改了一下,用户余额为0时会改变状态,也就是冻结用户

 调整好代码后接着测试扣减余额

注意下这里的请求方式和参数

可以看到状态和余额都改变了

 (7)IService批量新增

注:这里需要打开mysql的一个参数

将这个字段设置为true即可。

结语

这篇关于 MyBatis - Plus 学习的文章,其诞生如同一场与代码世界的深度邂逅。从暮色浸染的傍晚 6 点,到星光缀满夜空的凌晨 0:37,除去 30 分钟短暂的用餐时光,近 6 小时的全神贯注,最终打磨出这篇约 7000 字的学习记录。​

每一个字符都凝结着对 MyBatis - Plus 知识点的反复推敲,每一步操作过程的呈现都力求精准还原技术实践,每一处运行结果的记录都饱含对细节的极致追求 —— 这份从指尖流淌而出的文字,不仅是时间的沉淀,更是对 MyBatis - Plus 实操细节的细致捕捉。​

唯愿这份带着钻研热忱与满满诚意的记录,能为正在学习 MyBatis - Plus 的你扫清障碍,提供切实的参考与助益,让你的学习之路更顺畅。

最后附上文章全套代码

代码参考黑马程序员资料

UserController

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.web.bind.annotation.*;

import java.util.List;

@Api(tags = "用户管理相关接口")
@RequestMapping("/users")
@RestController
@RequiredArgsConstructor
public class UserController {

    private final IUserService userService;

    @ApiOperation("新增用户")
    @PostMapping
    public void saveUser(@RequestBody UserFormDTO userDTO){
        //1.把DTO转换成PO
        User user = BeanUtil.copyProperties(userDTO,User.class);
        //2.调用service完成新增
        userService.save(user);
    }

    @ApiOperation("删除用户")
    @DeleteMapping("/{id}")
    public void deleteUserById(@ApiParam("用户id") @PathVariable("id") Long id){
        userService.removeById(id);
    }

    @ApiOperation("查询用户")
    @GetMapping("/{id}")
    public UserVO queryUserById(@ApiParam("用户id") @PathVariable("id") Long id){
        //1.查询用户PO
        User user = userService.getById(id);
        //2.把PO转换成VO
        return BeanUtil.copyProperties(user,UserVO.class);
    }

    @ApiOperation("批量查询用户")
    @GetMapping
    public List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){
        //1.查询用户PO
        List<User> users = userService.listByIds(ids);
        //2.把PO转换成VO
        return BeanUtil.copyToList(users,UserVO.class);
    }

    @ApiOperation("扣减余额")
    @PutMapping("/{id}/deduction/{money}")
    public void deductBalance(
            @ApiParam("用户id") @PathVariable("id") Long id,
            @ApiParam("金额") @PathVariable("money") Integer money
    ){
        userService.deductBalance(id,money);
    }

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

User

package com.itheima.mp.domain.po;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.time.LocalDateTime;
@TableName("tb_user")
@Data
public class User {

    /**
     * 用户id
     */

    private Long id;

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

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

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

    /**
     * 详细信息
     */
    private String info;

    /**
     * 使用状态(1正常 2冻结)
     */
    private Integer status;

    /**
     * 账户余额
     */
    private Integer balance;

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

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

UserQuery

package com.itheima.mp.domain.query;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

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

UserVO

package com.itheima.mp.domain.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(description = "用户VO实体")
public class UserVO {

    @ApiModelProperty("用户id")
    private Long id;

    @ApiModelProperty("用户名")
    private String username;

    @ApiModelProperty("详细信息")
    private String info;

    @ApiModelProperty("使用状态(1正常 2冻结)")
    private Integer status;

    @ApiModelProperty("账户余额")
    private Integer balance;
}

UserMapper

package com.itheima.mp.mapper;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.mp.domain.po.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import org.springframework.core.Constants;

import java.util.List;

public interface UserMapper extends BaseMapper<User> {
//    List<User> queryUserByIds(@Param("ids") List<Long> ids);
    void updateBalanceByIds(@Param("ew") QueryWrapper<User> wrapper, @Param("amount") int amount);

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

UserServiceImpl

package com.itheima.mp.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
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;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Override
    @Transactional
    public void deductBalance(Long id, Integer money) {
        //1.查询用户
        User user = getById(id);
        //2.更新用户余额
        if(user == null || user.getStatus() == 2){
            throw new RuntimeException("用户不存在");
        }
        if(user.getBalance() < money){
            throw new RuntimeException("余额不足");
        }
        //余额为0时冻结用户
        int remainBalance = user.getBalance() - money;
        lambdaUpdate()
                .set(User::getBalance, remainBalance)
                .set(remainBalance == 0, User::getStatus, 2)
                .eq(User::getBalance,user.getBalance())
                .eq(User::getId, id)
                .update();
    }

    @Override
    public 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();
    }
}

IUserService

package com.itheima.mp.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.mp.domain.po.User;

import java.util.List;

public interface IUserService extends IService<User> {
    void deductBalance(Long id, Integer money);

    List<User> queryUsers(String name, Integer status, Integer minBalance, Integer maxBalance);
}

yaml

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
logging:
  level:
    com.itheima: debug
  pattern:
    dateformat: HH:mm:ss
#mybatis:
#  mapper-locations: classpath*:mapper/*.xml
mybitis-plus:
  mapper-locations: classpath*:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: false
  global-config:
    db-config:
      id-type: auto
      update-strategy: not_null
knife4j:
  enable: true
  openapi:
    group:
      default:
        group-name: default
        api-rule: package
        api-rule-resources:
          - com.itheima.mp.controller

UserMapperTest

package com.itheima.mp.mapper;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
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.List;

@SpringBootTest
class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    void testInsert() {
        User user = new User();
        //user.setId(5L);
        user.setUsername("张a三");
        user.setPassword("123");
        user.setPhone("18688990012");
        user.setBalance(200);
        user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        userMapper.insert(user);
    }

    @Test
    void testSelectById() {
        User user = userMapper.selectById(5L);
        System.out.println("user = " + user);
    }


    @Test
    void testQueryByIds() {
        List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L));
        users.forEach(System.out::println);
    }

    @Test
    void testUpdateById() {
        User user = new User();
        user.setId(5L);
        user.setBalance(20000);
        userMapper.updateById(user);
    }

    @Test
    void testDeleteUser() {
        userMapper.deleteById(5L);
    }

    //条件构造器测试案例
    @Test
    void textOne1() {
        //查询名字带o,并且存款大于1000的用户
        List<User> users = userMapper.selectList(new QueryWrapper<User>().like("username", "o").gt("balance", 1000));
        users.forEach(System.out::println);
    }

    @Test
    void textOne2() {
        //将张三存款改为10000
        User user = new User();
        user.setBalance(10000);
        QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "张a三");
        userMapper.update(user, wrapper);
    }

    @Test
    void textTwo1() {
        //基于UpdateWrapper更新id为1,2,3的用户余额减500
        UpdateWrapper<User> wrapper = new UpdateWrapper<User>().in("id", 1, 2, 3).setSql("balance = balance - 500");
        userMapper.update(null, wrapper);
    }

    @Test
    void textCustomSqlQuery() {
        //1.更新条件
        List<Long> ids = List.of(1L, 2L, 3L);
        int amount = 100;
        //2.定义条件
        QueryWrapper<User> wrapper = new  QueryWrapper<User>().in("id", ids);
        //3.调用 方法
        userMapper.updateBalanceByIds(wrapper, amount);
    }
}

IUserServiceTest

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 org.springframework.test.context.TestExecutionListeners;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class IUserServiceTest {
    @Autowired
    private IUserService userService;

    @Test
    void testSaveUser(){
        User user = new User();
        //user.setId(5L);
        user.setUsername("张三aaa");
        user.setPassword("123");
        user.setPhone("18688990012");
        user.setBalance(200);
        user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        userService.save(user);
    }

    @Test
    void testQuery(){
        List<User> list = userService.listByIds(List.of(1L, 2L, 3L));
        list.forEach(System.out::println);
    }

    @Test
    void testSaveBatch(){
        List<User> list = new ArrayList<>(10000);
        long b = System.currentTimeMillis();
        for (int i = 1; i <= 100000; i++) {
            User user = new User();
            user.setUsername("user" + i);
            user.setPassword("<PASSWORD>");
            user.setPhone("12345678901");
            user.setStatus(1);
            user.setBalance(100);
            user.setCreateTime(LocalDateTime.now());
            user.setUpdateTime(LocalDateTime.now());
            list.add(user);

            if(i%10000==0){
                userService.saveBatch(list);
                list.clear();
            }
        }
        long e = System.currentTimeMillis();
        System.out.println("耗时:"+(e-b));
    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.12</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.itheima.mp</groupId>
    <artifactId>mp-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mp-demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>org.mybatis.spring.boot</groupId>-->
<!--            <artifactId>mybatis-spring-boot-starter</artifactId>-->
<!--            <version>2.3.1</version>-->
<!--        </dependency>-->
<!--        mybits plus依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>
        <!--swagger-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
            <version>4.1.0</version>
        </dependency>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.11</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值