熟悉 mybatis-plus 的人都知道,mybatis-plus 提供两种包含预定义增删改查操作的接口:

  • com.baomidou.mybatisplus.core.mapper.BaseMapper
  • com.baomidou.mybatisplus.extension.service.IService

对比这两个接口,操作都差不多,名字有一点点改变,比如 BaseMapper 里面叫 insert() 的方法,在 IService 里面叫 save()。

其实我也不是很清楚为什么要单独设计 IService 接口,但是两者确实有区别,就是 IService 提供批处理操作,BaseMapper 没有。

另外,IService 的默认实现 com.baomidou.mybatisplus.extension.service.impl.ServiceImpl 就是调用 BaseMapper 来操作数据库,所以我猜 IService 是 Java 8 之前对 BaseMapper 所做的扩展,而 Java 8 之后,因为有了 default 方法,ServiceImpl 里面的东西其实都可以移到 BaseMapper 里面了。

除此之外还有就是 IService 依赖于 Spring 容器,而 BaseMapper 不依赖;BaseMapper 可以继承并添加新的数据库操作,IService 要扩展的话还是得调用 Mapper,显得有些多此一举。

所以,如果你既要使用批处理操作,又要添加自己的数据库操作,那就必须两个接口一起用。

比如在下面一个示例项目中,就同时存在两者:

// StudentService.java
@Service
public class StudentService extends ServiceImpl<StudentMapper, Student> {
}

// StudentMapper.java
@Component
public interface StudentMapper extends BaseMapper<Student> {

    @Select("select * from STUDENT where FIRST_NAME=#{firstName}")
    List<Student> selectByFirstName(@Param("firstName") String firstName);
}

这样每个实体都要创建两个文件,很麻烦。可不可以简化呢?可以,就像下面这样:

// StudentService.java
@Service
public class StudentService extends ServiceImpl<StudentMapper, Student> {

    public interface StudentMapper extends BaseMapper<Student> {

        @Select("select * from STUDENT where FIRST_NAME=#{firstName}")
        List<Student> selectByFirstName(@Param("firstName") String firstName);
    }
}

对,你没看错,就把 Mapper 直接写在 Service 里面就好。有人就会问了,这个 Mapper 能用吗?告诉你,能:

@Autowired
StudentService.StudentMapper studentMapper;

像上面这样引用过来,照常使用即可。

另外还有一种方式就是通过 Service 把 Mapper 暴露出来:

public class StudentService extends ServiceImpl<StudentMapper, Student> {

    public StudentMapper getMapper() {
        return this.baseMapper;
    }

    ...

这个 baseMapper 也是 StudentMapper 的实例。这样的话,使用的时候就只需要引用 StudentService 一个对象了:

List list = studentService.getMapper().selectByFirstName("First");

我为什么提这个 issue,因为这样用起来挺蛋疼。

Comment From: miemieYaho

看你打这么多字也挺辛苦的,不过我还是要说你java基础不行,理解能力有限

Comment From: yiding-he

@miemieYaho 所以你也不知道哪里有问题,于是关了。

Comment From: qmdx

mapper 属于数据库访问层 service 领域层,用来处理业务逻辑,多表操作业务方法的集合,mp 底层提供的 serviceImpl 对公共的领域方法抽象的提取,如果你不用该公共层也是可以的。

Comment From: yiding-he

@qmdx 行,我也不在乎领域什么的,因为我只想要批处理操作,所以在我看来就是 BaseMapper 功能不全的问题。确实 Service 也没必要用。自己建个 BaseMapper2 的接口,然后直接把 ServiceImpl 的代码拷贝过去就行了。

Comment From: miemieYaho

什么都是你看来,你看来,那你咋不自己去看源码了解原理呢?也不知道是谁给你的勇气在那里看来看去只动嘴不动脑的.

Comment From: yiding-he

@miemieYaho 这两个接口底下的源码都是操作数据库,跟领域层无关的,不知道你想说什么?看你这两条回复,完全没一点就事论事的态度,基本上都是人身攻击,不知道你自己意识到没有。

Comment From: qmdx

service 层返回 boolean 的结果, mapper 是数据库层的操作影响行数,这是有区别的 公共的 service 是省去了一些重复的判断控制层有的时候直接用而不是再去调用 mapper 层,跟你的情况来没有强制必须需要 service 层

Comment From: scxkd2016

这些作者太牛逼了,觉得别人都是屎,自己最香

Comment From: ChetWang

看你打这么多字也挺辛苦的,不过我还是要说你java基础不行,理解能力有限

这是我在github上见过的最霸气的commiter,不知如此藐视用户的勇气来自哪里?

Comment From: lbrant

很好的问题啊,不知道作者哪来的勇气,怼天怼地的

Comment From: TurboQiang

commiter的 被人绿了,所以火气很大。

Comment From: codeshan

commiter好多老年人

Comment From: mjiuming

什么都是你看来,你看来,那你咋不自己去看源码了解原理呢?也不知道是谁给你的勇气在那里看来看去只动嘴不动脑的.

NewB-Plus

Comment From: 1498743343

这些作者太牛逼了,觉得别人都是屎,自己最香

你说的太对了兄弟

Comment From: veione

commiter买的基金全绿了,火气大着呢,真是开源界的卧龙凤雏

Comment From: LiangART

666666,我也一直觉得Iservice的批处理在BaseMapper没有的设计太2了 这样的话还不如干脆别提供呢 就让我死心了自己去写

Comment From: xymengli

@qmdx 行,我也不在乎领域什么的,因为我只想要批处理操作,所以在我看来就是 BaseMapper 功能不全的问题。确实 Service 也没必要用。自己建个 BaseMapper2 的接口,然后直接把 ServiceImpl 的代码拷贝过去就行了。

我也有相同的问题 , 不知道你是如何解决的 , 我希望通过BaseMapper接口实现批量新增或者批量更新 , 而不是通过Service