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

  •  个人主页: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/*.xmlconfiguration:# 开启下划线转驼峰命名映射map-underscore-to-camel-case: true# 指定MyBatis日志实现方式,输出到控制台log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# 关闭二级缓存cache-enabled: falseglobal-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查询

//条件构造器测试案例@Testvoid textOne1(){//查询名字带o,并且存款大于1000的用户List<User> users = userMapper.selectList(new QueryWrapper<User>().like("username", "o").gt("balance", 1000));users.forEach(System.out::println);}@Testvoid textOne2(){//将张三存款改为10000User user = new User();user.setBalance(10000);QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "张a三");userMapper.update(user, wrapper);}

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

 可见余额已经修改为10000了

 2、基于UpdateWrapper更新

@Testvoid textTwo1(){//基于UpdateWrapper更新id为1,2,3的用户余额减500UpdateWrapper<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: trueopenapi:group:default:group-name: defaultapi-rule: packageapi-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("新增用户")@PostMappingpublic void saveUser(@RequestBody UserFormDTO userDTO){//1.把DTO转换成POUser 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.查询用户POUser user = userService.getById(id);//2.把PO转换成VOreturn BeanUtil.copyProperties(user,UserVO.class);}@ApiOperation("批量查询用户")@GetMapping("/{id}")public List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){//1.查询用户POList<User> users = userService.listByIds(ids);//2.把PO转换成VOreturn 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("新增用户")@PostMappingpublic void saveUser(@RequestBody UserFormDTO userDTO){//1.把DTO转换成POUser 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.查询用户POUser user = userService.getById(id);//2.把PO转换成VOreturn BeanUtil.copyProperties(user,UserVO.class);}@ApiOperation("批量查询用户")@GetMappingpublic List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){//1.查询用户POList<User> users = userService.listByIds(ids);//2.把PO转换成VOreturn 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.查询用户POList<User> users = userService.queryUsers(query.getName(),query.getStatus(),query.getMinBalance(),query.getMaxBalance());//2.把PO转换成VOreturn 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@Transactionalpublic 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();}@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();}
}

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=truetype: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: 123456
logging:level:com.itheima: debugpattern:dateformat: HH:mm:ss
#mybatis:
#  mapper-locations: classpath*:mapper/*.xml
mybitis-plus:mapper-locations: classpath*:mapper/*.xmlconfiguration:map-underscore-to-camel-case: truecache-enabled: falseglobal-config:db-config:id-type: autoupdate-strategy: not_null
knife4j:enable: trueopenapi:group:default:group-name: defaultapi-rule: packageapi-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 {@Autowiredprivate UserMapper userMapper;@Testvoid 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);}@Testvoid testSelectById() {User user = userMapper.selectById(5L);System.out.println("user = " + user);}@Testvoid testQueryByIds() {List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L));users.forEach(System.out::println);}@Testvoid testUpdateById() {User user = new User();user.setId(5L);user.setBalance(20000);userMapper.updateById(user);}@Testvoid testDeleteUser() {userMapper.deleteById(5L);}//条件构造器测试案例@Testvoid textOne1() {//查询名字带o,并且存款大于1000的用户List<User> users = userMapper.selectList(new QueryWrapper<User>().like("username", "o").gt("balance", 1000));users.forEach(System.out::println);}@Testvoid textOne2() {//将张三存款改为10000User user = new User();user.setBalance(10000);QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "张a三");userMapper.update(user, wrapper);}@Testvoid textTwo1() {//基于UpdateWrapper更新id为1,2,3的用户余额减500UpdateWrapper<User> wrapper = new UpdateWrapper<User>().in("id", 1, 2, 3).setSql("balance = balance - 500");userMapper.update(null, wrapper);}@Testvoid 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 {@Autowiredprivate IUserService userService;@Testvoid 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);}@Testvoid testQuery(){List<User> list = userService.listByIds(List.of(1L, 2L, 3L));list.forEach(System.out::println);}@Testvoid 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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/90981.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/90981.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/90981.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

odoo-060 git版本:发布/生产版本落后开发版本部署

文章目录问题起源目前解决问题起源 周五提交了一个版本&#xff0c;本来打算使用这个版本的&#xff0c;周末更新。 下一个功能比较复杂&#xff0c;周一提交&#xff0c;结果周末没有更新&#xff0c;导致现在还有没测试过的不能发布的。 说明&#xff1a; 原来只有一个mast…

YotoR模型:Transformer与YOLO新结合,打造“又快又准”的目标检测模型

【导读】在目标检测领域&#xff0c;YOLO系列以其高效的推理速度广受欢迎&#xff0c;而Transformer结构则在精度上展现出强大潜力。如何兼顾二者优势&#xff0c;打造一个“又快又准”的模型&#xff0c;是近年来研究热点之一。本文介绍的一项新研究——YotoR&#xff08;You …

白杨SEO:流量的本质是打开率?搞用户搜索流量的玩法怎么做?

大家好&#xff0c;我是白杨SEO&#xff0c;专注研究SEO十年以上&#xff0c;全网SEO流量实战派&#xff0c;AI搜索优化研究者。上周六参加了生财航海家在杭州举行的私域运营大会&#xff0c;主题是围绕私域获客&#xff0c;私域IP&#xff0c;AI私域&#xff0c;精细化管理。白…

Java优雅使用Spring Boot+MQTT推送与订阅

在物联网&#xff08;IoT&#xff09;和智能设备横行的今天&#xff0c;你有没有遇到这样的问题&#xff1a;服务端需要实时把报警、状态更新、控制指令推送给客户端&#xff1b;安卓 App、嵌入式设备、网页等终端&#xff0c;需要轻量且稳定的连接方式&#xff1b;HTTP 太“重…

多目标粒子群优化(MOPSO)解决ZDT1问题

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

Coze Studio概览(三)--智能体管理

本文简要分析了Coze Studio中智能体管理功能&#xff0c;包括功能、架构以及核心流程。Coze Studio 智能体管理功能分析 1. 智能体管理架构概览 Coze Studio的智能体管理系统基于DDD架构&#xff0c;主要包含以下核心模块&#xff1a; 后端架构层次&#xff1a; API层 (coze): …

idea运行tomcat日志乱码问题

原因在于idea和tomcat文件编码格式不一样。可以把idea编码改成UTF-8 File | Settings | Editor | File Encodings 里面把GBK都改成UTF-8help里面 Edit Custom VM Options 添加一行-Dfile.encodingUTF-8重启idea

Javaweb - 13 - AJAX

发送请求的几种方式1. 浏览器的地址框中输入地址&#xff0c;回车2. html --> head --> scrip / linkimg 自动发送请求&#xff0c;无需手动触发3. a 标签&#xff0c;form 表单标签需要手动控制提交产生&#xff0c;且往往需要在新的页面上获得响应信息4. 运行 JS 代码…

qt常用控件-06

文章目录qt常用控件-06spinBox/doubleSpinBoxdateTimeEditdialSliderlistWIdgettableWidgettreeWidget结语很高兴和大家见面&#xff0c;给生活加点impetus&#xff01;&#xff01;开启今天的编程之路&#xff01;&#xff01; 今天我们进一步c11中常见的新增表达 作者&#…

小智源码分析——音频部分(二)

一、利用创建好的对象来调用音频服务 上周从上图的getaudiocode()方法进去感受了一下底层小智的构造如何实现。所以用一个codec来接收我们所构造的音频对象。下来是用构造好的音频对象来调用音频初始化服务Initialize&#xff0c;因为启动函数Application函数的类中有audio_ser…

菜鸟的C#学习(四)

文章目录一、格式说明符1.1、数字格式说明符&#xff08;适用于数值类型&#xff1a;int, double, decimal 等&#xff09;1. 标准数字格式2. 自定义数字格式1.2、日期时间格式说明符&#xff08;适用于 DateTime, DateTimeOffset&#xff09;1. 标准日期时间格式2. 自定义日期…

基于黑马教程——微服务架构解析(二)

本篇文章基于黑马程序员的微服务课程内容&#xff0c;结合个人学习过程中的理解与思考进行整理。本节将围绕以下几个问题展开&#xff1a;什么是网关和配置管理前面那篇文章&#xff0c;我们了解如何把一个单体的项目拆成分布式微服务项目&#xff0c;并且讲解一下各个服务之间…

Text2SQL智能问答系统开发(一)

开发一个面向企业的chatBI工作流 已完成 基础 Text2SQL 功能实现 实现用户输入自然语言问题后&#xff0c;系统能够自动生成 SQL 并执行返回结果。用户交互优化 支持用户通过补充信息对查询进行调整&#xff0c;提升易用性。模糊时间处理机制 对“最近”“近期”等模糊时间关…

Python HTML模块详解:从基础到实战

一、模块体系全景图 Python生态中处理HTML的工具可分为三大层级&#xff1a; 标准库基础层&#xff1a;html模块 html.parser第三方增强层&#xff1a;BeautifulSoup&#xff08;搭配解析器&#xff09;专业级工具层&#xff1a;lxml requests-html 二、标准库核心模块详解…

PyTorch常用Tensor形状变换函数详解

PyTorch常用Tensor形状变换函数详解 在PyTorch中&#xff0c;对张量&#xff08;Tensor&#xff09;进行形状变换是深度学习模型构建中不可或缺的一环。无论是为了匹配网络层的输入要求&#xff0c;还是为了进行数据预处理和维度调整&#xff0c;都需要灵活运用各种形状变换函数…

自主智能Agent如何重塑工作流自动化:技术、经济与未来展望

自主智能Agent的崛起与工作流自动化的范式革命2025年7月&#xff0c;当OpenAI向付费用户推出具备网页浏览和代码执行能力的ChatGPT Agent时&#xff0c;工作流自动化领域迎来了一场静默但彻底的革命。这款不再满足于简单问答的智能体&#xff0c;在一个安全的虚拟计算机环境中运…

技术架构、行业应用、工具链整合、挑战应对及未来趋势五大模块,引用多个权威来源数据与开源项目实现细节。

以下是一份关于AI技术落地的实战经验总结报告&#xff0c;结合代码示例、可视化图表与行业案例&#xff0c;内容分为技术架构、行业应用、工具链整合、挑战应对及未来趋势五大模块&#xff0c;引用多个权威来源数据与开源项目实现细节。AI技术落地实战指南&#xff1a;从架构设…

第 9 篇:神经网络初探——当AI拥有了“大脑”,世界从此不同

《人工智能AI之机器学习基石》系列⑨ 专栏核心理念: 用通俗语言讲清楚机器学习的核心原理,强调“洞察 + 技术理解 + 应用连接”,构建一个完整的、富有启发性的知识体系。

音频焦点 Android Audio Focus 进阶

旧焦点处理 示例调用链: requestAudioFocus() → propagateFocusLossFromGain_syncAf() → handleFocusLossFromGain()。 系统事件(如来电)→ 强制焦点变化 → handleFocusLossFromGain()。 函数 propagateFocusLossFromGain_syncAf 焦点持有者发生的焦点丢失通知 主要功能…

MFC UI对话框

文章目录对话框模态对话框创建销毁关闭CDialog::OnCancel()EndDialog()CDialog::DestroyWindow()非模态对话框创建销毁关闭delete this对话框 模态对话框 ​​阻塞父窗口​​&#xff0c;强制用户先处理对话框。关闭前父窗口无法响应事件。 创建 推荐&#xff1a;非指针方式…