本文详解mybatis-plus中getbyid()与getone(lambdaquerywrapper)在单条记录查询中的核心差异:前者基于主键精确查询、查不到抛异常;后者按条件查询、查不到返回null,二者语义与行为均不等价。
在Spring Boot + MyBatis-Plus开发中,初学者常误认为getById(id)和getOne(new LambdaQueryWrapper().eq(Entity::getId, id))功能完全等价——实际上二者在设计意图、执行逻辑与异常处理上存在本质区别,直接混用可能导致空指针异常或业务逻辑隐性失败。
该方法专为主键查询设计,底层调用selectById,会生成形如 SELECT * FROM category WHERE id = ? 的SQL。其特点是:
// ✅ 推荐:ID已知时首选,配合try-catch或全局异常处理器
try {
Category category = categoryService.getById(categoryId);
String categoryName = category.getCategoryName(); // 安全调用
} catch (IllegalArgumentException e) {
throw new BusinessException("分类不存在,ID:" + categoryId);
}该方法本质是 SELECT * FROM category WHERE ... LIMIT 1,适用于任意字段组合查询。关键特性包括:
// ❌ 危险写法:未判空导致NPE LambdaQueryWrapperwrapper = new LambdaQueryWrapper<>(); wrapper.eq(Category::getId, categoryId); Category category = categoryService.getOne(wrapper); String name = category.getCategoryName(); // category可能为null! // ✅ 正确用法:必须显式判空 Category category = categoryService.getOne(wrapper); if (category == null) { throw new BusinessException("分类未找到,ID :" + categoryId); } String categoryName = category.getCategoryName();
| 维度 | getById(id) | getOne(wrapper) |
|---|---|---|
| 设计目的 | 主键精确查询 | 通用条件查询(取第一条) |
| 空值处理 | 查不到抛异常(可配置) | 查不到返回null |
| SQL生成 | SELECT * FROM table WHERE id=? | SELECT * FROM table WHERE ... LIMIT 1 |
| 性能 | 最优(主键索引直达) | 依赖WHERE条件是否命中索引 |
| 适用场景 | ID确定且业务要求强一致性 | 多条件筛选、分页前取样、存在性校验 |
归根结底,二者不是“等价替换”,而是不同语义场景下的工具选择——理解差异,方能写出健壮、可维护的查询代码。