• 《你还在写sql语句吗?》人生苦短,进入MybatisPlus的丝滑体验


    一、发展历程

      依稀记得大学期间,类中写sql语句的日子,一个sql语句占据了大部分时间,到后来hibernate的出现算是解决了这一痛点。工作

    后,我们又接触到了mybatis这样的框架,瞬间感觉这个世界美好了很多。但岂能就此满足。借机与mybatis的出现,我们已经将好多

    逻辑处理搬到xml文件中利用sql进行处理,耦合性就变得十分大,如果没有MybatisPlus的出现(后文简称MP),这可能就是我们当前认

    知下最常规且常用的操作,直到我接触Python后,再到MP,瞬间感觉“人生苦短,快用MP”(此处我们只讨论MP带来的效率提升,至

    于他的局限性,此文不做赘述后续会单独讲解)

      废话不多说,让我们从零开始,进入MP的体验。

    二、MP旅程

    2.1、优势及特性

      请参考MP官网

    2.2、pom文件引入

    <!-- mybatisPlus与SpringBoot的整合 -->
    <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.3.1</version>
    </dependency>
    
    <!-- 根据表逆向生成代码 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.3.1</version>
    </dependency>
                        

    2.3、流程讲解

      1、利用逆向工程生成entity与mapper接口,mapper xml文件(后续专门出一片逆向工程)。

      2、注入Mapper操作或者利用service层操作(主要用于屁来给你操作,自带事务)。

      3、我们需要考虑的就是,如何组装条件。

      4、多张表操作时,在service进行数据组装。

      5、将返回的数据,按照前端要求封装到返回的dto中。

    2.4、Entity

      与数据库的表一一对应,将表列抽象成实体类属性,逆向生成后,原则上不能改动,统一在dto进行处理

    @Data
    @EqualsAndHashCode(callSuper = false)
    @Accessors(chain = true)
    @ApiModel(value="SiteProjectSource对象", description="角色与项目来源关联表")
    public class SiteProjectSource implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @TableId(value = "id", type = IdType.AUTO)
        private Integer id;
    
        private Integer roleId;
    
        private String roleName;
    
        private String projectSource;
    
        private Date updateTime;
    }

    2.5、Mapper接口

      默认不提供接口,如果业务需要特殊处理,我们需要自己扩展MapperEX项目,进行继承扩展

    默认生成的文件,一般不做改动。

    public interface SiteProjectSourceMapper extends BaseMapper<SiteProjectSource> {
    
    }

    2.6、Mapper XML文件

      同上

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.cbi.site.provider.mapper.SiteProjectSourceMapper">
    
    </mapper>

    2.7、IService接口

      继承的IService接口,是MP对外提供的

    public interface ISiteProjectSourceService extends IService<SiteProjectSource> {
    
        SResponseBean updateProjectSource(SRequestBean<SiteProjectSourceUpdateReq> updateReq) throws BaseBusinessException;
    
        SResponseBean queryProjectSourcePage(SRequestBean<SiteProjectSourcePageQueryReq> pageQueryReq) throws  Exception;
    }

    2.8、Service实现类

    @Service
    public class SiteProjectServiceImpl extends ServiceImpl<SiteProjectMapper, SiteProject> implements ISiteProjectService {
    
        @Autowired
        private SiteProjectMapper siteProjectMapper;
    
        @Autowired
        private SiteWorkOrderMapper siteWorkOrderMapper;
    
        /**
         * 创建项目信息
         * @param createReqs 请求参数
         * */
        @Override
        public SResponseBean createProject(SRequestBean<List<SiteProjectCreateReq>> createReqs) throws BaseBusinessException {
            List<SiteProjectCreateReq> body = createReqs.getBody();
            List<SiteProject> siteProjects = SBeanUtils.convertToResponse(SiteProject.class, body);
         //批量插入需要使用this调用,即MP的IService提供的接口
    boolean flag = this.saveBatch(siteProjects); AssertUtils.isTrue(flag, SCodeEnum.INSERT_ERROR); return SResponseUtil.output(SCodeEnum.SUCCESS); } @Override public SResponseBean enableOrdisableProject(SRequestBean<List<SiteProjectModifyReq>> modifyReqs, String flag) throws BaseBusinessException { //利用lambda组装查询条件
         List
    <SiteProject> siteProjects = modifyReqs.getBody().stream().map( r -> new SiteProject().setId(r.getId()).setEnabled(flag) ).collect(Collectors.toList());
         //利用ids进行批量更新
    boolean updateFlag = this.updateBatchById(siteProjects); AssertUtils.isTrue(updateFlag, SCodeEnum.INSERT_ERROR); return SResponseUtil.output(SCodeEnum.SUCCESS); } @Override public SResponseBean updateProject(SRequestBean<SiteProjectUpdateReq> updateReq) throws BaseBusinessException { SiteProjectUpdateReq body = updateReq.getBody(); SiteProject siteProject = BeanUtil.toBean(body, SiteProject.class);
         //单条更新,我们利用Mapper即可
    int updateNum = siteProjectMapper.updateById(siteProject); AssertUtils.isTrue(updateNum>0, SCodeEnum.UPDATE_ERROR); return SResponseUtil.output(SCodeEnum.SUCCESS); } @Override public SResponseBean queryProject(SRequestBean<SiteProjectQueryReq> queryReq) throws BaseBusinessException { SiteProjectQueryReq body = queryReq.getBody(); SiteProject siteProject = BeanUtil.toBean(body, SiteProject.class);

              //官方建议利用LambdaQueryWrapper,灵活易于扩展,支持链式拼接条件,不用写死列名
              /*QueryWrapper<SiteProject> queryWrapper = new QueryWrapper<SiteProject>().setEntity(siteProject);
              if(Objects.nonNull(body.getUpdateTimeStart())) {
                  queryWrapper.ge("update_time", body.getUpdateTimeStart());
              }

          if(Objects.nonNull(body.getUpdateTimeEnd())) {
            queryWrapper.le("update_time", body.getUpdateTimeEnd());
          }*/

          LambdaQueryWrapper<SiteProject> queryWrapper = Wrappers.<SiteProject>lambdaQuery();
          //组装日期区间
          if(Objects.nonNull(body.getUpdateTimeStart())) {
            queryWrapper.ge(SiteProject::getUpdateTime, body.getUpdateTimeStart());
          }
          if(Objects.nonNull(body.getUpdateTimeEnd())) {
            queryWrapper.le(SiteProject::getUpdateTime, body.getUpdateTimeEnd());
          }

            List<SiteProject> siteProjects = siteProjectMapper.selectList(queryWrapper);
            return SResponseUtil.output(siteProjects);
        }
    
    @Override
    public SResponseBean queryProjectPage(SRequestBean<SiteProjectPageQueryReq> pageQueryReq) throws BaseBusinessException { SiteProjectPageQueryReq body = pageQueryReq.getBody(); SiteProject siteProject = BeanUtil.toBean(body, SiteProject.class); QueryWrapper<SiteProject> queryWrapper = new QueryWrapper<SiteProject>() .setEntity(siteProject); DBUtils.PackageDateInterval(queryWrapper,"update_time",body.getUpdateTimeStart(),body.getUpdateTimeEnd()); Page<SiteProject> page = new Page<>(body.getPageNum(), body.getPageSize());
         //天然的分页查询 Page
    <SiteProject> siteProjectPage = siteProjectMapper.selectPage(page, queryWrapper); return SResponseUtil.output(siteProjectPage); }

      
      @Override
      public SResponseBean queryProjectNameList(SRequestBean<SiteProjectNameListQueryReq> queryReq) throws BaseBusinessException {
      /*官方不推荐这种写法,入侵性高,需要写死字段列名
      我们采用直接查询所有,然后通过lambda进行去重
      QueryWrapper<SiteProject> queryWrapper = new QueryWrapper<>();
      queryWrapper.select("DISTINCT name").eq("source", queryReq.getBody().getSource());*/
      //构建查询条件
      LambdaQueryWrapper<SiteProject> queryWrapper = Wrappers.<SiteProject>lambdaQuery()
    .eq(SiteProject::getSource, queryReq.getBody().getSource());
      List<SiteProject> siteProjectList= siteProjectMapper.selectList(queryWrapper);
      //针对结果进行去重
      List<SiteProject> distinctList = siteProjectList.stream().collect(
    Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getName()))),
    ArrayList::new));
      //转换成返回的dto
      List<SiteProjectNameListRes> siteProjectNameListResList = SBeanUtils.convertToResponse(SiteProjectNameListRes.class, distinctList);
      return SResponseUtil.output(siteProjectNameListResList);
      }
    }

    2.9、总结

      没有一条sql,不用做事务控制,不用写for循环取插入等等,这一切都全赖MP的功劳,对于大部分场景,MP已经可以满足我们

    日常的操作,我们不用关注sql是如何拼接的,如何运行的,将时间用于处理业务逻辑上。并且在当下流行的思想下,我们提倡最大

    可能的解耦,数据层我们最好单表操作,利用service层继续处理,得利于lambda表达式的诞生,集合的处理变得更加丝滑,效率大

    大提升。我们需要不断思考,不断学习,避免重复造轮子,人生苦短,我更喜欢开箱即用。但使用过后,我更建议大家撸撸源码,

    了解底层的实现。这样路才能走得远且扎实。

    三、娱乐时光

    3.1、新鲜事 

      贵州公交车司机结果公布,蓄意报复社会。

      每一条人名,背后都是一个家庭,将自己对社会的不公,发泄在20多条人命上,不管怎么说,都是无法被原谅。

    但愿逝者安息,生者引以为戒,心理健康是当下最应被重视起来,希望大家平日少于人发生冲突,因为你永远不知道,

    对方是否可能做出极端的行为。

    3.2、歌曲推荐

      爱的故事(上),每一名男孩子都有过青春期的懵懂,都有过暗恋的经历,听苦情歌,不过“全为爱上了你偏偏你不知”,

    祝愿全天下程序员都有归宿,名花有主的,可不要贪杯哦。

    3.3、影视推荐

      源代码 Source Code (2011),如果你也对平行世界有兴趣,不然看看这部影片。

     3.4、养眼壁纸

  • 相关阅读:
    Thinkphp框架下对某个字段查询数据的时候进行唯一过滤,返回唯一不同的值
    Thinkphp框架下(同服务器下)不同二级域名之间session互通共享设置
    CentOS 6.8下Apache绑定多个域名的方法
    CentOS 6.8下更改Apache默认网站安装目录
    Ubuntu 16.04系统下安装PHP5.6*
    Ubuntu 16.04系统下解决Vim乱码问题
    jQuery 核心
    Ubuntu 16.04系统下安装Discuz出现“HTTP ERROR 500”目前无法处理此请求
    BCB6 重装后的项目编译莫名问题
    LR6 碱性电池才能带动微软鼠标
  • 原文地址:https://www.cnblogs.com/weipt0106/p/13296600.html
Copyright © 2020-2023  润新知