告别繁琐的业务层代码,MyBatis-Plus带你飞~

学习要求

良好的java基础, 熟悉SpringBoot框架,熟悉Mybatis框架

教学目标

了解并掌握MyBatis-Plus业务层的实现

视频教程

MyBatisPlus实战教程与开发建议

概念

Java项目一般使用三层结构开发:

表现层:接收请求,调用业务方法处理请求,响应请求

业务层:也叫服务层,实现业务逻辑,调用持久层实现数据组合操作

持久层:完成数据的CRUD操作

前面讲的Mapper接口操作属于持久层,如果项目加入服务层,那代码该如何构建呢?

传统的业务层

使用MyBatis-Plus之前,传统业务层构建方式:以员工操作为例子

步骤1:构建员工业务层服务接口

public interface IEmployeeService {
    void save(Employee employee);
    void update(Employee employee);
    void delete(Long id);
    Employee get(Long id);
    List<Employee> list();
}

步骤2:实现员工业务层接口

@Service
public class EmployeeServiceImpl implements IEmployeeService {
    @Autowired
    private EmployeeMapper mapper;

    @Override
    public void save(Employee employee) {
        mapper.insert(employee);
    }

    @Override
    public void update(Employee employee) {
        mapper.updateById(employee);  //必须全量更新
    }

    @Override
    public void delete(Long id) {
        mapper.deleteById(id);
    }

    @Override
    public Employee get(Long id) {
        return mapper.selectById(id);
    }
    @Override
    public List<Employee> list() {
        return mapper.selectList(null);
    }
}

步骤3:实现服务方法测试

传统业务层服务方法需要自己调用Mapper接口方法去实现,相对麻烦。再看MyBatis-Plus提供简化操作

MyBatis-Plus业务层

步骤1:构建员工业务层服务接口

/**
*1>自定义一个业务服务接口:IEmployeeService,继承父接口:IService
*2>明确指定父接口泛型:当前接口操作实体对象:Employee
*/
public interface IEmployeeService extends IService<Employee> {
}

步骤2:实现员工业务层接口

/**
*1>定义服务接口实现类,实现IEmployeeService接口
*2>继承通用的父接口实现类:ServiceImpl
*3>明确指定通用的父接口实现类2个泛型:
*    1:当前服务类操作的实体对象对应的Mapper接口:EmployeeMapper
*    2:当前服务类操作的实体对象:Employee
*/
@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {
}

步骤3:实现服务方法测试

@SpringBootTest
public class ServiceTest {
    @Autowired
    private IEmployeeService employeeService;
    @Test
    public void testSave(){
        Employee employee = new Employee();
        employee.setAdmin(1);
        employee.setAge(18);
        employee.setDeptId(1L);
        employee.setEmail("zhangsan@163.com");
        employee.setName("zhangsan");
        employee.setPassword("111");
        employeeService.save(employee);
    }

    @Test
    public void testUpdate(){
        Employee employee = new Employee();
        employee.setId(1327139013313564673L);
        employee.setAdmin(1);
        employee.setAge(18);
        employee.setDeptId(1L);
        employee.setEmail("zhangsan@163.com");
        employee.setName("zhangxiaosan");
        employee.setPassword("111");
        employeeService.updateById(employee);
    }
    @Test
    public void testDelete(){
        employeeService.removeById(11L);
    }
    @Test
    public void testGet(){
        System.out.println(employeeService.getById(11L));
    }

    @Test
    public void testList(){
        List<Employee> employees = employeeService.list();
        employees.forEach(System.err::println);
    }

}

常用服务层api

 

上面就是IService接口提供的实现方法,几乎涵盖了数据库常规操作。

方法解析

思考一个问题,IService接口是怎么实现的?

以IEmployeeService 接口中的getById() 方法为例子

/**
* 根据 ID 查询
*
* @param id 主键ID
*/
default T getById(Serializable id) {
    return getBaseMapper().selectById(id);
}

源码上,getById是一个接口默认方法,默认实现是调用getBaseMapper()对象去执行selectById方法

/**
* 获取对应 entity 的 BaseMapper
*
* @return BaseMapper
*/
BaseMapper<T> getBaseMapper();

getBaseMapper方法也是IService接口定义的方法,继续追踪其接口实现:

ServiceImpl类的getBaseMapper方法

public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {

    @Autowired
    protected M baseMapper;

    @Override
    public M getBaseMapper() {
        return baseMapper;
    }
}

从上面代码可以看到baseMapper是使用@Autowired 方式从spring容器中注入的,具体类型是泛型对象M, 而在定义EmployeeServiceImpl类时,具体代码:

@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {
}

可以确认,以EmployeeServiceImpl为例子, 那么ServiceImpl中M的泛型就是EmployeeMapper类型,那么ServiceImpl可以等价

public class ServiceImpl<EmployeeMapper extends BaseMapper<T>, T> implements IService<T> {

    @Autowired
    protected EmployeeMapper baseMapper;

    @Override
    public EmployeeMapper getBaseMapper() {
        return baseMapper;
    }
}

最后IService方法中getById

/**
* 根据 ID 查询
*
* @param id 主键ID
*/
default T getById(Serializable id) {
    return getBaseMapper().selectById(id);
}

等价于:

/**
* 根据 ID 查询
*
* @param id 主键ID
*/
default T getById(Serializable id) {
    //其中的baseMapper就是employeeMapper
    return baseMapper.selectById(id);
}

到这,可以确定IService接口中方法底层都是使用Mapper接口方法实现,那么IService 接口方法操作就可以同理可得啦。

总结

MyBatis-Plus Service层编写得益于IService接口与ServiceImpl接口实现,能满足大部分常规的CRUD操作需求,后续如果业务复杂后,可以自己去拓展接口。

MyBatis-Plus Service层这种操作模式相对简单,在中小型项目中使用非常推荐,如果在复杂项目需要酌情考虑,Service层通过继承方式实现便利,同时也引入很多不必要的方法,同时让代码结构复杂话,后期维护是个麻烦。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浪飞yes

我对钱没兴趣~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值