《你還在寫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);
} }
2.9、總結
沒有一條sql,不用做事務控制,不用寫for迴圈取插入等等,這一切都全賴MP的功勞,對於大部分場景,MP已經可以滿足我們日常的操作,
我們不用關注sql是如何拼接的,如何執行的,將時間用於處理業務邏輯上。並且在當下流行的思想下,我們提倡最大可能的解耦,資料層我們
最好單表操作,利用service層繼續處理,得利於lambda表示式的誕生,集合的處理變得更加絲滑,效率大大提升。我們需要不斷思考,不斷
學習,避免重複造輪子,人生苦短,我更喜歡開箱即用。但使用過後,我更建議大家擼擼原始碼,瞭解底層的實現。這樣路才能走得遠且紮實。
三、娛樂時光
3.1、新鮮事
貴州公交車司機結果公佈,蓄意報復社會。
每一條人名,背後都是一個家庭,將自己對社會的不公,發洩在20多條人命上,不管怎麼說,都是無法被原諒。
但願逝者安息,生者引以為戒,心理健康是當下最應被重視起來,希望大家平日少於人發生衝突,因為你永遠不知道,
對方是否可能做出極端的行為。
3.2、歌曲推薦
愛的故事(上),每一名男孩子都有過青春期的懵懂,都有過暗戀的經歷,聽苦情歌,不過“全為愛上了你偏偏你不知”,
祝願全天下程式設計師都有歸宿,名花有主的,可不要貪杯哦。
3.3、影視推薦
原始碼 Source Code(2011),我最喜歡影片中關於平行世界的暗示。