一、發展歷程
依稀記得大學期間,類中寫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、養眼壁紙