深入浅出MyBatis-Plus实战指南
一、引言
MyBatis-Plus作为MyBatis的增强工具包,解决了传统ORM框架95%以上的重复劳动。本文将通过构建"电商平台商品管理系统"的完整案例,带您深入理解MP的核心功能。
二、环境准备
2.1 Maven依赖配置
xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
<!-- Mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
2.2 数据库脚本
sql
CREATE DATABASE IF NOT EXISTS `ecommerce`;
USE `ecommerce`;
CREATE TABLE `product` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(64) NOT NULL,
`price` decimal(10,2) NOT NULL,
`stock` int(11) NOT NULL,
`description` text,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_price` (`price`)
);
三、核心功能实现
3.1 实体类定义
java
@Data
@TableName("product")
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@NotBlank(message = "商品名称不能为空")
private String name;
@NotNull(message = "价格不能为空")
@DecimalMin(value = "0.01", inclusive = true)
private BigDecimal price;
@Min(value = 0, message = "库存不能小于0")
private Integer stock;
private String description;
}
3.2 Mapper接口继承
java
public interface ProductMapper extends BaseMapper<Product> {
// 不需要编写任何SQL语句
}
3.3 服务层基础操作
java
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductMapper productMapper;
// 单个添加
public boolean addProduct(Product product) {
return productMapper.insert(product) > 0;
}
// 批量添加(性能优化)
public boolean batchAdd(List<Product> products) {
return productMapper.insertBatchSomeColumn(products) > 0;
}
// 根据ID修改
public boolean updateById(Product product) {
return productMapper.updateById(product) > 0;
}
// 批量修改状态
public boolean updateStatusBatch(List<Long> ids, Integer status) {
UpdateWrapper<Product> wrapper = new UpdateWrapper<>();
wrapper.set("status", status).in("id", ids);
return productMapper.update(null, wrapper) > 0;
}
// 物理删除(慎用!)
public boolean deleteById(Long id) {
return productMapper.deleteById(id) > 0;
}
// 推荐使用的逻辑删除
public boolean removeByIdLogical(Long id) {
return productMapper.deleteById(new Product().setId(id));
}
}
3.4 复杂查询实战
3.4.1 条件构造器应用
java
// 创建时间在最近7天的热销商品
QueryWrapper<Product> wrapper = new QueryWrapper<>();
wrapper.ge("price", 100)
.between("createTime", LocalDateTime.now().minusDays(7), LocalDateTime.now())
.orderByDesc("salesVolume");
List<Product> hotProducts = productMapper.selectList(wrapper);
3.4.2 动态排序实现
java
Page<Product> querySortedProducts(Map<String, String> sortParams) {
Page<Product> page = new Page<>(1, 10);
QueryWrapper<Product> wrapper = new QueryWrapper<>();
// 处理排序参数
if(sortParams != null && !sortParams.isEmpty()) {
wrapper.orderBy(true, sortParams.get("order").equals("asc"), sortParams.get("field"));
}
return productMapper.selectPage(page, wrapper);
}
3.5 分页查询优化
java
public PageDTO<Product> getPaginatedProducts(int pageNum, int pageSize) {
Page<Product> page = new Page<>(pageNum, pageSize);
QueryWrapper<Product> wrapper = new QueryWrapper<>();
wrapper.likeRight(true, "name", "手机")
.ge("price", 2000)
.orderByDesc("createTime");
IPage<Product> result = productMapper.selectPage(page, wrapper);
// 封装返回结果
PageDTO<Product> dto = new PageDTO<>();
dto.setTotal(result.getTotal());
dto.setPages(result.getPages());
dto.setCurrent(result.getCurrent());
dto.setRecords(result.getRecords());
return dto;
}
四、高级特性应用
4.1 逻辑删除配置
yaml
# application.yml配置
mybatis-plus:
global-config:
db-config:
logic-delete-value: 1
logic-not-delete-value: 0
4.2 乐观锁实现
java
@Service
public class ConcurrencyService {
@Autowired
private ProductMapper productMapper;
// 并发场景下的安全更新
public boolean safeUpdateStock(Long productId, int quantity) {
Product product = new Product();
product.setId(productId);
product.setStock(quantity);
// 自动版本控制
return productMapper.updateById(product) == 1;
}
}
4.3 自动填充字段
java
// 配置自动填充
@Configuration
public class MyMetaObjectHandlerConfig implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, () -> LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, () -> LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, () -> LocalDateTime.now());
}
}
五、注意事项
- 主键策略选择:推荐使用雪花算法生成分布式ID
- 批量操作注意:默认batchSize=1000,可根据实际调整
- 谨慎使用updateAll()方法,可能造成全表更新
- 事务管理需配合@Transactional使用
六、扩展学习路径
- 学习Condition构造器的更多用法
- 研究自定义通用service实现
- 探索代码生成器的实际使用
- 阅读官方文档中的拦截器机制
通过本教程,您可以快速掌握MyBatis-Plus在企业级项目中的应用技巧,大幅提高开发效率的同时保证代码质量。