# 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插件,需要完成一些自定义配置

## 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;
}
```
# 插件