# mp-demo **Repository Path**: su27sk/mp-demo ## Basic Information - **Project Name**: mp-demo - **Description**: MyBatis-Plus 精细化进阶,包含 CRUD 操作、主键策略、字段映射、全局配置等实战案例。 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-07 - **Last Updated**: 2026-05-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Mybatis-Plus入门 ## 起步配置 ```java // maven依赖 com.baomidou mybatis-plus-boot-starter 3.5.3.1 // 接口继承 public interface UserMapper extends BaseMapper {} ``` ## 常用注解 ```java MybatisPlus 是如何获取实现 CRUD 的数据库表信息的? 默认以类名驼峰转下划线作为表名 默认把名为 id 的字段作为主键 默认把变量名驼峰转下划线作为表的字段名 MybatisPlus 的常用注解有哪些? @TableName:指定表名称及全局配置 @TableId:指定 id 字段及相关配置 @TableField:指定普通字段及相关配置 IdType 的常见类型有哪些? AUTO、ASSIGN_ID、INPUT 使用 @TableField 的常见场景是? 成员变量名与数据库字段名不一致 成员变量名以 is 开头,且是布尔值 成员变量名与数据库关键字冲突 成员变量不是数据库字段 ``` ## 常用配置 ```java # mp的常用配置 mybatis-plus: type-aliases-package: com/liuwei/mp/domain/po # 对应实体bean global-config: db-config: id-type: auto # id生成策略 ``` # Mybatis-Plus核心 ## 条件构造器 ```java // ----- QueryWrapper ----- @Test void testQueryWrapper() { // 1.构建查询条件 QueryWrapper wrapper = new QueryWrapper() .select("id","username","info","balance") .like("username","o") .ge("balance",1000); // 2.查询 List users = userMapper.selectList(wrapper); users.forEach(System.out::println); } @Test void testUpdateByQueryWrapper() { User user = new User(); user.setBalance(2000); QueryWrapper wrapper = new QueryWrapper().eq("username", "jack"); userMapper.update(user,wrapper); } // ----- UpdateWrapper ----- @Test void testUpdateWrapper() { List ids = List.of(1L,2L,4L); UpdateWrapper wrapper = new UpdateWrapper() .setSql("balance = balance - 200") .in("id", ids); userMapper.update(null,wrapper); } // ----- LambdaQueryWrapper ----- @Test void testLambdaQueryWrapper() { LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper() .select(User::getId, User::getUsername, User::getInfo, User::getBalance) .like(User::getUsername, "o") .ge(User::getBalance, 1000); List users = userMapper.selectList(lambdaQueryWrapper); users.forEach(System.out::println); } ``` ## 自定义SQL ```java // 自定义sql @Test void testCustomSqlUpdate() { // 1.更新条件 List ids = List.of(1L,2L,4L); int amount = 200; // 2.定义条件 QueryWrapper wrapper = new QueryWrapper().in("id", ids); // 3.调用自定义的sql方法 userMapper.updateBalanceByIds(wrapper, amount); } public interface UserMapper extends BaseMapper { void updateBalanceByIds(@Param(Constants.WRAPPER) QueryWrapper wrapper, @Param("amount") int amount); } UPDATE tb_user SET balance = balance - #{amount} ${ew.customSqlSegment} ``` ## IService - 业务层和数据层继承实现的架子 ```java package com.liuwei.mp.service; import org.springframework.stereotype.Service; public interface IUserService extends IService { } package com.liuwei.mp.service.impl; @Service public class UserServiceImpl extends ServiceImpl implements IUserService { } package com.liuwei.mp.mapper; public interface UserMapper extends BaseMapper { } ``` - lambda方法:可以同时完成条件,查询,执行sql ```java @Service @Transactional public class UserServiceImpl extends ServiceImpl implements IUserService { @Override public void deductBalance(Long id, Integer money) { // 1.查询用户 User user = getById(id); // 2.校验用户状态 if (user == null || user.getStatus() == 2) { throw new RuntimeException("用户状态异常!"); } // 3.校验余额是否充足 if (user.getBalance() < money) { throw new RuntimeException("用户余额不足!"); } // 4.扣减余额 // baseMapper.deductBalance(id,money); int remainBalance = user.getBalance() - money; lambdaUpdate() .set(User::getBalance,remainBalance) .set(remainBalance == 0, User::getStatus, 2) .eq(User::getId,id) .eq(User::getBalance,user.getBalance()) // 乐观锁 .update(); } @Override public List 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(); } ``` - 批量插入方法,可以采用分批插入的方法,然后记得开启Mysql的rewriteBatchedStatements=true配置 ```java private User buildUser(int i) { User user = new User(); user.setUsername("user_" + i); user.setPassword("123"); user.setPhone("" + (18688190000L + i)); user.setBalance(2000); user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}"); user.setCreateTime(LocalDateTime.now()); user.setUpdateTime(user.getCreateTime()); return user; } // 批处理插入 @Test void testSaveBatch() { // 每次批量插入1000条数据,插入100次就是10万条 List list = new ArrayList<>(1000); Long b = System.currentTimeMillis(); for (int i = 1; i <= 100000; i++){ list.add(buildUser(i)); // 每一千次插入一次 if (i % 1000 == 0) { userService.saveBatch(list); // 清空集合 list.clear(); } } Long e = System.currentTimeMillis(); System.out.println("耗时: " + (e - b)); } ``` # 扩展功能 ## 代码生成器 这里采用MybatisPlus插件,需要完成一些自定义配置 ![MybatisPlus插件.png](pic/MybatisPlus%E6%8F%92%E4%BB%B6.png) ## Db静态方法 Db = MyBatis-Plus 提供的一个静态工具类作用:不用注入 Service、不用注入 Mapper,随时随地直接查数据库 ```java @Override public List queryUserAndAddressByIds(List ids) { // 1.查询用户 List users = listByIds(ids); if (CollUtil.isEmpty(users)) { return Collections.emptyList(); } // 2.查询地址 List userIds = users.stream().map(User::getId).collect(Collectors.toList()); List
addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list(); List addressVOList = BeanUtil.copyToList(addresses, AddressVO.class); Map> addressMap = new HashMap<>(0); if(CollUtil.isNotEmpty(addressVOList)) { addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId)); } List list = new ArrayList<>(users.size()); for (User user:users){ UserVO userVO = BeanUtil.copyProperties(user, UserVO.class); userVO.setAddresses(addressMap.get(user.getId())); list.add(userVO); } return list; } ``` ## 逻辑删除 logic-delete-field: deleted :开启全局逻辑删除; 删除 → 改 deleted=1 ;查询 → 自动只查 deleted=0 ;数据永远不会真删除,安全! ```java @SpringBootTest public class IAddressServiceTest { @Autowired private IAddressService addressService; @Test void testLogicDelete() { addressService.removeById(59L); Address address = addressService.getById(59L); System.out.println("address = " + address); } @Test void testLogicQuery(){ Address address = addressService.getById(59L); System.out.println("address = " + address); } } ``` ## 枚举处理器 构造枚举类 ```java @Getter public enum UserStatus { NORMAL(1,"正常"), FROZEN(2,"冻结") ; @EnumValue // 做好数据库字段和枚举值的映射 private final int value; @JsonValue // 表面接口返回desc字段 private final String desc; UserStatus(int value,String desc) { this.value = value; this.desc = desc; ``` bean实体类修改字段属性 private UserStatus status; ## Json处理器 构造一个bean,准备将数据库的json属性的字段接受 ```java @Data @NoArgsConstructor @AllArgsConstructor(staticName = "of") public class UserInfo { private Integer age; private String intro; private String gender; } ``` bean类处理 ```java @Data // 指定表名字 @TableName(value = "tb_user",autoResultMap = true) // 开启自动映射 public class User { @TableField(typeHandler = JacksonTypeHandler.class) // 准备json处理器 private UserInfo info; } ``` # 插件