最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于Mybatis-Plus?Wrapper是否應(yīng)該出現(xiàn)在Servcie類中

 更新時間:2023年05月09日 12:37:21   作者:羅小爬EX  
最近在做代碼重構(gòu),代碼工程采用了Controller/Service/Dao分層架構(gòu),Dao層使用了Mybatis-Plus框架,本文帶領(lǐng)大家學(xué)習(xí)Mybatis-Plus?Wrapper應(yīng)該出現(xiàn)在Servcie類中嗎,需要的朋友可以參考下

一、問題

最近在做代碼重構(gòu),代碼工程采用了Controller/Service/Dao分層架構(gòu),Dao層使用了Mybatis-Plus框架。
在查看Service層時發(fā)現(xiàn)如下代碼:

@Service
public class SampleServiceImpl implements SampleService {
    @Resource
    private SampleMapper sampleMapper;
    @Override
    public SampleTo findById(Long id) {
        Sample sample = this.sampleMapper.selectOne(Wrappers.<Sample>lambdaQuery()
                //僅查詢指定的column
                .select(Sample::getId, Sample::getName, Sample::getDate)
                //查詢條件 id = #{id}
                .eq(Sample::getId, id)
        );
        return (SampleTo) BaseAssembler.populate(sample, new SampleTo());
    }
    @Override
    public PageInfo<SampleTo> findListByDto(SampleQueryDto sampleQueryDto) {
        //開啟分頁
        PageHelperUtil.startPage(sampleQueryDto);
        //查詢分頁列表
        List<Sample> sampleList = this.sampleMapper.selectList(Wrappers.<Sample>lambdaQuery()
                //查詢條件 id = #{id}
                .eq(Objects.nonNull(sampleQueryDto.getId()), Sample::getId, sampleQueryDto.getId())
                //查詢條件 name like concat('%', #{name}, '%')
                .like(StringUtils.hasText(sampleQueryDto.getName()), Sample::getName, sampleQueryDto.getName())
                //查詢條件 type = #{type}
                .eq(StringUtils.hasText(sampleQueryDto.getType()), Sample::getType, sampleQueryDto.getType())
                //查詢條件 date >= #{startDate}
                .ge(Objects.nonNull(sampleQueryDto.getStartDate()), Sample::getDate, sampleQueryDto.getStartDate())
                //查詢條件 date <= #{endDate}
                .le(Objects.nonNull(sampleQueryDto.getEndDate()), Sample::getDate, sampleQueryDto.getEndDate()));
        //轉(zhuǎn)換分頁結(jié)果
        return PageHelperUtil.convertPageInfo(sampleList, SampleTo.class);
    }
    @Override
    public List<SampleTo> findListByCondition(String name, String type) {
        List<Sample> sampleList = this.sampleMapper.selectList(Wrappers.<Sample>lambdaQuery()
                //查詢條件 name like concat('%', #{name}, '%')
                .like(StringUtils.hasText(name), Sample::getName, name)
                //查詢條件 type = #{type}
                .eq(StringUtils.hasText(type), Sample::getType, type)
        );
        return BaseAssembler.populateList(sampleList, SampleTo.class);
    }
	@Override
    public SampleDetailTo findDetailById(Long id) {
        return this.sampleMapper.findDetail(id);
    }
    @Override
    public Integer add(SampleAddDto sampleAddDto) {
        Sample sample = new Sample();
        BaseAssembler.populate(sampleAddDto, sample);
        return this.sampleMapper.insert(sample);
    }
}

dao層代碼:

public interface SampleMapper extends BaseMapper<Sample> {
	//SQL腳本通過XML進行定義
    SampleDetailTo findDetail(@Param("id") Long id);
}

如上Service代碼中直接使用Mybatis-Plus框架提供的Wrapper構(gòu)造器,寫的時候是挺爽,不用再單獨為SampleMapper接口寫XML腳本了,直接在Service類中都完成了,但是我不推薦這種寫法。

分層架構(gòu)的本意是通過分層來降低、隔離各層次的復(fù)雜度,
各層間僅通過接口進行通信,層間僅依賴抽象接口,不依賴具體實現(xiàn),
只要保證接口不變可以自由切換每層的實現(xiàn)。

上述Service類中直接引用了Dao層實現(xiàn)框架Mybatis-Plus中的Wrappers類,盡管Servcie層依賴了Dao層的Mapper接口,但是Mapper接口中的參數(shù)Wrapper卻是Dao層具體實現(xiàn)Mybatis-Plus所獨有的,試想我們現(xiàn)在Dao層用的Mybatis-Plus實現(xiàn),后續(xù)如果想將Dao層實現(xiàn)切換為Spring JPA,那Mybatis-Plus中Wrapper是不都要替換,那Servcie層中的相關(guān)Wrapper引用也都要進行替換,我們僅是想改變Dao實現(xiàn),卻不得不把Servcie層也進行修改。同時Service層本該是寫業(yè)務(wù)邏輯代碼的地方,但是卻耦合進了大量的Wrapper構(gòu)造邏輯,代碼可讀性差,難以捕捉到核心業(yè)務(wù)邏輯。

二、優(yōu)化建議

那是不是Mybatis-Plus中的Wrapper就不能用了呢?我的答案是:能用,只是方式?jīng)]用對。
Wrapper絕對是個好東西,方便我們構(gòu)造Sql,也可以將我們從繁瑣的XML腳本中解救出來,但是不能跨越層間界限。

優(yōu)化建議如下:

  • 移除Servcie中的Wrapper使用
  • Java8+之后接口提供了默認方法的支持,可通過給Dao層Mapper接口添加default方法使用Wrapper
  • 單表相關(guān)的操作 - 通過Dao層Mapper接口的default方法直接使用Wrapper進行實現(xiàn),提高編碼效率
  • 多表關(guān)聯(lián)的復(fù)雜操作 - 通過Dao層Mapper接口和XML腳本的方式實現(xiàn)

優(yōu)化后的Service層代碼如下:

@Service
public class SampleServiceImpl implements SampleService {
    @Resource
    private SampleMapper sampleMapper;
    @Override
    public SampleTo findById(Long id) {
        Sample sample = this.sampleMapper.findInfoById(id);
        return (SampleTo) BaseAssembler.populate(sample, new SampleTo());
    }
    @Override
    public SampleDetailTo findDetailById(Long id) {
        return this.sampleMapper.findDetail(id);
    }
    @Override
    public PageInfo<SampleTo> findListByDto(SampleQueryDto sampleQueryDto) {
        //開啟分頁
        PageHelperUtil.startPage(sampleQueryDto);
        //查詢分頁列表
        List<Sample> sampleList = this.sampleMapper.findList(sampleQueryDto);
        //轉(zhuǎn)換分頁結(jié)果
        return PageHelperUtil.convertPageInfo(sampleList, SampleTo.class);
    }
    @Override
    public List<SampleTo> findListByCondition(String name, String type) {
        List<Sample> sampleList = this.sampleMapper.findListByNameAndType(name, type);
        return BaseAssembler.populateList(sampleList, SampleTo.class);
    }
    @Override
    public Integer add(SampleAddDto sampleAddDto) {
        Sample sample = new Sample();
        BaseAssembler.populate(sampleAddDto, sample);
        return this.sampleMapper.insert(sample);
    }
}

優(yōu)化后的Dao層代碼:

public interface SampleMapper extends BaseMapper<Sample> {
    default Sample findInfoById(Long id) {
        return this.selectOne(Wrappers.<Sample>lambdaQuery()
                //僅查詢指定的column
                .select(Sample::getId, Sample::getName, Sample::getDate)
                //查詢條件 id = #{id}
                .eq(Sample::getId, id)
        );
    }
    default List<Sample> findList(SampleQueryDto sampleQueryDto) {
        return this.selectList(Wrappers.<Sample>lambdaQuery()
                //查詢條件 id = #{id}
                .eq(Objects.nonNull(sampleQueryDto.getId()), Sample::getId, sampleQueryDto.getId())
                //查詢條件 name like concat('%', #{name}, '%')
                .like(StringUtils.hasText(sampleQueryDto.getName()), Sample::getName, sampleQueryDto.getName())
                //查詢條件 type = #{type}
                .eq(StringUtils.hasText(sampleQueryDto.getType()), Sample::getType, sampleQueryDto.getType())
                //查詢條件 date >= #{startDate}
                .ge(Objects.nonNull(sampleQueryDto.getStartDate()), Sample::getDate, sampleQueryDto.getStartDate())
                //查詢條件 date <= #{endDate}
                .le(Objects.nonNull(sampleQueryDto.getEndDate()), Sample::getDate, sampleQueryDto.getEndDate())
        );
    }
    default List<Sample> findListByNameAndType(String name, String type) {
        return this.selectList(Wrappers.<Sample>lambdaQuery()
                //查詢條件 name like concat('%', #{name}, '%')
                .like(StringUtils.hasText(name), Sample::getName, name)
                //查詢條件 type = #{type}
                .eq(StringUtils.hasText(type), Sample::getType, type)
        );
    }
    //SQL腳本通過XML進行定義)     
    SampleDetailTo findDetail(@Param("id") Long id);
}

優(yōu)化后的Servcie層完全移除了對Wrapper的依賴,將Servcie層和Dao層實現(xiàn)進行解耦,同時Dao層通過Java8+接口的默認方法同時支持Wrapper和XML的使用,整合編碼和XML腳本的各自優(yōu)勢。

三、Repository模式

經(jīng)過優(yōu)化過后,Service層代碼確實清爽了許多,移除了Mybatis-Plus的Wrapper構(gòu)造邏輯,使得Service層可以更專注于業(yè)務(wù)邏輯的實現(xiàn)。但是細心的小伙伴還是會發(fā)現(xiàn)Servcie層仍舊依賴了Mybatis的分頁插件PageHelper中的PageHelper類、PageInfo類,PageHelper插件也是技術(shù)綁定的(強綁定到Mybatis),既然我們們之前強調(diào)了Servcie層與Dao層間的界限,如此在Servcie層使用PageHelper也是越界了,例如后續(xù)如果切換Spring JPA,那PageHelper在Servcie層的相關(guān)的引用也都需要調(diào)整。

真正做到業(yè)務(wù)和技術(shù)解耦,可以參考DDD中的Repository(倉庫、資源庫)模式

  • 單獨定義通用的分頁查詢參數(shù)DTO、分頁查詢結(jié)果DTO(與具體技術(shù)解耦)
  • 定義Repository接口,僅依賴聚合、通用分頁查詢參數(shù)DTO、分頁查詢結(jié)果DTO
  • 定義Repository接口的實現(xiàn)類,具體實現(xiàn)可依賴如Mybatis、JPA等Dao框架,在Repository的具體實現(xiàn)類中完成轉(zhuǎn)換:
    • 領(lǐng)域模型(聚合)<==> 數(shù)據(jù)實體
    • 通用分頁查詢參數(shù)DTO、結(jié)果DTO <==> Dao框架的分頁參數(shù)、結(jié)果(如PageHelper、IPage等)

DDD映射到代碼層面,改動還是比較大的,所以在這次重構(gòu)代碼的過程中并沒有真正采用DDD Repository模式,
而是僅從Servcie中移除Mybatis-Plus Wrapper便結(jié)束了,雖沒有完全將Service層與Dao層實現(xiàn)(PageHelper)解耦,
但在Service層移除Wrapper構(gòu)造邏輯后,使得Service層代碼更清爽,可讀性更好了,重構(gòu)過程的代碼改動量也在可接收的范圍內(nèi)。

到此這篇關(guān)于Mybatis-Plus Wrapper應(yīng)該出現(xiàn)在Servcie類中嗎?的文章就介紹到這了,更多相關(guān)Mybatis-Plus Wrapper內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java反射機制詳解

    Java反射機制詳解

    這篇文章主要介紹了Java反射機制,首先簡單介紹了反射機制的預(yù)備知識,進一步分析了Java反射機制的原理、實現(xiàn)技巧與應(yīng)用方法,需要的朋友可以參考下
    2015-12-12
  • springboot?實戰(zhàn):異常與重定向問題

    springboot?實戰(zhàn):異常與重定向問題

    這篇文章主要介紹了springboot實戰(zhàn):異常與重定向問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java使用JDBC實現(xiàn)Oracle用戶認證的方法詳解

    Java使用JDBC實現(xiàn)Oracle用戶認證的方法詳解

    這篇文章主要介紹了Java使用JDBC實現(xiàn)Oracle用戶認證的方法,結(jié)合實例形式分析了java使用jdbc實現(xiàn)數(shù)據(jù)庫連接、建表、添加用戶、用戶認證等操作流程與相關(guān)注意事項,需要的朋友可以參考下
    2017-08-08
  • SpringBoot中實時監(jiān)控Redis命令流的實現(xiàn)

    SpringBoot中實時監(jiān)控Redis命令流的實現(xiàn)

    在Redis的日常使用和調(diào)試中,監(jiān)控命令流有助于我們更好地理解 Redis的工作狀態(tài),Redis提供了MONITOR命令,可以實時輸出Redis中所有客戶端的命令請求,本文將介紹如何使用Jedis實現(xiàn)這一功能,并對比telnet實現(xiàn)MONITOR機制的工作方式,需要的朋友可以參考下
    2024-11-11
  • Spring中使用JSR303請求約束判空的實現(xiàn)

    Spring中使用JSR303請求約束判空的實現(xiàn)

    這篇文章主要介紹了Spring中使用JSR303請求約束判空的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • SpringBoot JWT實現(xiàn)token登錄刷新功能

    SpringBoot JWT實現(xiàn)token登錄刷新功能

    JWT本身是無狀態(tài)的,這點有別于傳統(tǒng)的session,不在服務(wù)端存儲憑證。這種特性使其在分布式場景,更便于擴展使用。接下來通過本文給大家分享SpringBoot JWT實現(xiàn)token登錄刷新功能,感興趣的朋友一起看看吧
    2021-09-09
  • Java實現(xiàn)發(fā)送短信驗證碼功能

    Java實現(xiàn)發(fā)送短信驗證碼功能

    這篇文章主要為大家詳細介紹了Java實現(xiàn)發(fā)送短信驗證碼功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • SpringBoot讀取外部配置文件的方法

    SpringBoot讀取外部配置文件的方法

    這篇文章主要介紹了SpringBoot讀取外部配置文件的方法,以端口配置為例,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02
  • idea2020.3.3集成maven及遇到的坑(推薦)

    idea2020.3.3集成maven及遇到的坑(推薦)

    這篇文章主要介紹了idea2020.3.3集成maven的相關(guān)知識,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • 解決Aop @AfterReturning因返回類型不一致導(dǎo)致無法執(zhí)行切面代碼

    解決Aop @AfterReturning因返回類型不一致導(dǎo)致無法執(zhí)行切面代碼

    這篇文章主要介紹了解決Aop @AfterReturning因返回類型不一致導(dǎo)致無法執(zhí)行切面代碼問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07

最新評論

太白县| 海淀区| 灵宝市| 广汉市| 天柱县| 和政县| 东港市| 辽阳市| 吉木乃县| 紫金县| 荔浦县| 洛扎县| 株洲市| 驻马店市| 玉林市| 栖霞市| 崇礼县| 湟中县| 宁远县| 乌拉特中旗| 安溪县| 邢台市| 武冈市| 城市| 神农架林区| 钦州市| 赤城县| 珠海市| 承德市| 宁津县| 玛沁县| 大悟县| 鹤庆县| 百色市| 黄大仙区| 汕尾市| 曲麻莱县| 兴化市| 高唐县| 富源县| 棋牌|