引言
在使用 MyBatis-Plus 时,我们经常看到两种 Mapper 调用方式:通过 ServiceImpl 父类的 baseMapper 或直接注入的自定义 Mapper。许多开发者认为 baseMapper.selectById() 和 categreyMapper.selectById() 是完全等价的——但事实真的如此吗?本文将结合代码案例,揭示二者的关键差异和潜在陷阱
1. baseMapper
它的类型由泛型参数 M 决定(即 ServiceImpl<M, T> 中的 M),不继承 ServiceImpl → baseMapper 字段不存在
// ServiceImpl 中定义的 baseMapper
public class ServiceImpl<M extends BaseMapper<T>, T> {
protected M baseMapper; // 由 MyBatis-Plus 自动注入
//T 是操作的实体类型
}
例子
public class WmsGoodServiceImpl
extends ServiceImpl<GoodsMapper, WmsGood> //这里的GoodsMaper决定了baseMapper类型
implements WmsGoodService //WmsGood是要操作的实体类
结论:
也就是说basMapper是由你的service实现类继承的ServiceImpl<GoodsMapper, WmsGood>中的GoodsMapper决定的,
补充:
1.baseMapper 是由 Spring 容器自动注入的,
public abstract class ServiceImpl<M extends BaseMapper<T>, T> {
@Autowired // ✅ 关键注解
protected M baseMapper;
}
- @Autowired 注解:明确告诉 Spring 需要自动注入这个字段
- 泛型 M:决定了注入的具体类型
2. 注入触发条件
@Service
public class WmsGoodServiceImpl
extends ServiceImpl<GoodsMapper, WmsGood> { // ✅ 泛型定义
}
关键步骤:
1.Spring 扫描:发现 @Service 注解的 WmsGoodServiceImpl
2.泛型解析:识别 ServiceImpl<GoodsMapper, WmsGood> 中的 GoodsMapper
3.Bean 查找:在容器中查找 GoodsMapper 类型的 Bean
3.代理注入:将 MyBatis-Plus 动态生成的 GoodsMapper 代理对象注入
2.自定义Mapper
如上述例子如果@Resorce注入的是如果是GoodsMapper,那么baseMapper(继承自父类)和手动注入的 GoodsMapper 调用的方法没有本质区别,二者指向同一个 Mapper 实例,执行的方法逻辑完全一致。
如果调用其他的自定义Mapper你是看不到selectById之类的方法的,除非他本身也是继承了BaseMapper的mapper类