<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一款 IDEA 插件幫你優(yōu)雅轉(zhuǎn)化 DTO、VO、BO、PO、DO

          共 5809字,需瀏覽 12分鐘

           ·

          2022-04-13 10:00

          點(diǎn)擊關(guān)注上方“Stephen”,

          設(shè)為“置頂或星標(biāo)”,第一時(shí)間送達(dá)干貨

          POJO 的定義是無規(guī)則簡(jiǎn)單的對(duì)象,在日常的代碼分層中 pojo 會(huì)被分為VO、BO、 PO、 DTO
          VO (view object/value object)表示層對(duì)象
          1、前端展示的數(shù)據(jù),在接口數(shù)據(jù)返回給前端的時(shí)候需要轉(zhuǎn)成VO
          2、個(gè)人理解使用場(chǎng)景,接口層服務(wù)中,將DTO轉(zhuǎn)成VO,返回給前臺(tái)
          B0(bussines object)業(yè)務(wù)層對(duì)象
          1、主要在服務(wù)內(nèi)部使用的業(yè)務(wù)對(duì)象
          2、可以包含多個(gè)對(duì)象,可以用于對(duì)象的聚合操作
          3、個(gè)人理解使用場(chǎng)景,在服務(wù)層服務(wù)中,由DTO轉(zhuǎn)成BO然后進(jìn)行業(yè)務(wù)處理后,轉(zhuǎn)成DTO返回到接口層
          PO(persistent object)持久對(duì)象
          1、出現(xiàn)位置為數(shù)據(jù)庫(kù)數(shù)據(jù),用來存儲(chǔ)數(shù)據(jù)庫(kù)提取的數(shù)據(jù)
          2、只存儲(chǔ)數(shù)據(jù),不包含數(shù)據(jù)操作
          3、個(gè)人理解使用場(chǎng)景,在數(shù)據(jù)庫(kù)層中,獲取的數(shù)據(jù)庫(kù)數(shù)據(jù)存儲(chǔ)到PO中,然后轉(zhuǎn)為DTO返回到服務(wù)層中
          DTO(Data Transfer Object)數(shù)據(jù)傳輸對(duì)象
          1、在服務(wù)間的調(diào)用中,傳輸?shù)臄?shù)據(jù)對(duì)象
          2、個(gè)人理解,DTO是可以存在于各層服務(wù)中(接口、服務(wù)、數(shù)據(jù)庫(kù)等等)服務(wù)間的交互使用DTO來解耦
          DO(domain object)領(lǐng)域?qū)嶓w對(duì)象
          DO 現(xiàn)在主要有兩個(gè)版本:
          ①阿里巴巴的開發(fā)手冊(cè)中的定義,DO( Data Object)這個(gè)等同于上面的PO
          ②DDD(Domain-Driven Design)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中,DO(Domain Object)這個(gè)等同于上面的BO
          參考文檔:
          https://juejin.cn/post/6952848675924082718
          https://juejin.cn/post/6844904046097072141
          https://zhuanlan.zhihu.com/p/264675395
          插件名稱:Simple Object Copy

          1. 定義方法出入?yún)?/span>

          2. 光標(biāo)定位方法內(nèi),使用快捷鍵ALT+INSERT(WIN) 、 command + N(mac) ,或者右鍵鼠標(biāo)選擇Generate,彈出生成選項(xiàng)框后,選擇genCopyMethod,代碼就生成好了

          需要手寫的代碼

          一鍵生成后的展示

          復(fù)雜對(duì)象轉(zhuǎn)化展示(一鍵生成后的展示)

          復(fù)雜對(duì)象轉(zhuǎn)化源碼示例
          @Data
          public?class?UserVO {
          ????private?String?name;
          ????private?Date?entryDate;
          ????private?String?userId;
          ????private?List roleList;
          ????private?RoomVO room;
          ????public?static?UserVO convertToUserVO(UserDTO item) {
          ????????if?(item ==?null) {
          ????????????return?null;
          ????????}
          ????????UserVO result =?new?UserVO();
          ????????result.setName(item.getName());
          ????????result.setEntryDate(item.getEntryDate());
          ????????result.setUserId(item.getUserId());
          ????????List roleList = item.getRoleList();
          ????????if?(roleList ==?null) {
          ????????????result.setRoleList(null);
          ????????}?else?{
          ?????result.setRoleList(roleList.stream().map(UserVO::convertToRoleVO).collect(Collectors.toList());
          ????????}
          ????????result.setRoom(convertToRoomVO(item.getRoom()));
          ????????return?result;
          ????}

          ????public?static?RoomVO convertToRoomVO(RoomDTO item) {
          ????????if?(item ==?null) {
          ????????????return?null;
          ????????}
          ????????RoomVO result =?new?RoomVO();
          ????????result.setRoomId(item.getRoomId());
          ????????result.setBuildingId(item.getBuildingId());
          ????????result.setRoomName();
          ????????result.setBuildingName();
          ????????return?result;
          ????}

          ????public?static?RoleVO convertToRoleVO(RoleDTO item) {
          ????????if?(item ==?null) {
          ????????????return?null;
          ????????}
          ????????RoleVO result =?new?RoleVO();
          ????????result.setRoleId(item.getRoleId());
          ????????result.setRoleName(item.getRoleName());
          ????????result.setCreateTime(item.getCreateTime());
          ????????return?result;
          ????}
          }
          @Data
          public?class?UserDTO {
          ????private?String?name;
          ????private?Date?entryDate;
          ????private?String?userId;
          ????private?List roleList;
          ????private?RoomDTO room;
          }

          @Data
          public?class?RoleVO {
          ????private?String?roleId;
          ????private?String?roleName;
          ????private?LocalDateTime createTime;
          }

          @Data
          public?class?RoleDTO {
          ????private?String?roleId;
          ????private?String?roleName;
          ????private?LocalDateTime createTime;
          }

          @Data
          public?class?RoomVO {
          ????private?String?roomId;
          ????private?String?buildingId;
          ????private?String?roomName;
          ????private?String?buildingName;

          }

          @Data
          public?class?RoomDTO {
          ????private?String?roomId;
          ????private?String?buildingId;
          }


          1.無入侵市面上有很多類似的工具類,比較常用的有

          1、Spring BeanUtils?(copyProperties)

          2、Cglib ?BeanCopier (copyProperties)

          3、Apache BeanUtils (copyProperties)

          4、Apache PropertyUtils?(copyProperties)

          5、Dozer

          6、mapstruct

          7、JSON 序列化 再反序列化

          這些工具,不僅要引入相應(yīng)的依賴jar包,而且對(duì)代碼有入侵,要調(diào)用對(duì)應(yīng)得api方法才能進(jìn)行轉(zhuǎn)化,一旦遇到類型不一致,字段名稍有變動(dòng),就需要另寫java代碼補(bǔ)全字段,整體代碼非常丑陋。
          舉例:

          1. mapstruct

          同樣的代碼,,不僅要引入依賴、寫如下轉(zhuǎn)化mapper,還要,在對(duì)應(yīng)地方調(diào)用對(duì)應(yīng)api(代碼入侵驗(yàn)證),然而Simple Object Copy 只需要一鍵生成。
          RoomDTO中不存在的roomName、buildingName還要mapstruct另寫方法,很容易忽略。源實(shí)體中不存在的屬性,沒有提示,小心前端總是問為啥都是null。
          在Simple Object Copy 插件代碼生成后,不存在的字段也生成了空方法,直接編譯提示補(bǔ)充,不容易忽略
          需要手寫的代碼
          @Mapper(componentModel =?"spring",uses = {RoleVOMapper.class,RoomVOMapper.class})
          public?interface?UserMapper?{
          ????UserConverter INSTANCE = Mappers.getMapper(UserConverter.class);
          ????
          ????UserVO?toUserVO(UserDTO userDTO);
          }

          @Mapper(componentModel =?"spring")
          public?interface?RoleMapper?{
          ????RoleVO?toRoleVO(RoleDTO roleDTO);
          }

          @Mapper(componentModel =?"spring")
          public?interface?RoomMapper?{
          ????RoomVO?toRoomVO(RoomDTO roomDTO);
          }


          public?class?Main?{
          ????public?static?void?main(String[] args)?{
          ????????UserDTO user = ;
          ????????UserVO userVO = UserMapper.INSTANCE.toUserVO(user);
          ????????userVO.getRoomVO().setRoomName("大廳1");
          ????????userVO.getRoomVO().setBuildingName("尚德樓");
          ????}
          }
          1. BeanUtils
          性能稍差。
          不支持復(fù)雜對(duì)象還是要寫大量代碼,代碼字段不清晰不易理解,別人接手難。RoomDTO中不存在的roomName、buildingName還要BeanUtils另寫方法,很容易忽略。源實(shí)體中不存在的屬性,沒有提示,小心前端總是問為啥都是null。
          需要手寫的代碼
          @Data
          public?class?UserVO?{
          ????private?String name;
          ????private?Date entryDate;
          ????private?String userId;
          ????private?List roleList;
          ????private?RoomVO room;
          ????public?static?UserVO?convertToUserVO(UserDTO item)?{
          ????????if?(item ==?null) {
          ????????????return?null;
          ????????}
          ????????UserVO result =?new?UserVO();
          ????????BeanUtils.copyProperties(item,result);
          ????????List roleList = item.getRoleList();
          ????????if?(roleList ==?null) {
          ????????????result.setRoleList(null);
          ????????}?else?{
          ?????result.setRoleList(roleList.stream().map(UserVO::convertToRoleVO).collect(Collectors.toList());
          ????????}
          ????????result.setRoom(convertToRoomVO(item.getRoom()));
          ????????return?result;
          ????}

          ????public?static?RoomVO?convertToRoomVO(RoomDTO item)?{
          ????????if?(item ==?null) {
          ????????????return?null;
          ????????}
          ????????RoomVO result =?new?RoomVO();
          ????????BeanUtils.copyProperties(item,result);
          ????????
          ????????result.setRoomName();
          ????????result.setBuildingName();
          ????????return?result;
          ????}

          ????public?static?RoleVO?convertToRoleVO(RoleDTO item)?{
          ????????if?(item ==?null) {
          ????????????return?null;
          ????????}
          ????????RoleVO result =?new?RoleVO();
          ????????BeanUtils.copyProperties(item,result);
          ????????return?result;
          ????}
          }
          2.性能優(yōu)勢(shì)
          相比上面的工具類,不是使用反射、就是是用代理、序列化操作。相比于純正的set方法去轉(zhuǎn)化,差距不是一個(gè)量級(jí)。此次不贅述。
          3.靈活性、兼容性
          跟上述工具類相比插件有很大優(yōu)勢(shì),不再贅述,下面我們比較一下,我之前常用的idea插件generateO2O

          在此推薦其他一個(gè)我常用插件:generateAllSetter,搭配食用更佳,
          4. 如何下載?
          打開idea plugins,切market place 搜索:Simple Object Copy

          來源:juejin.cn/post/7053264631262871583

          瀏覽 75
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  污污网站在线免费观看 | 影音先锋美女 | 波多野结衣做爱视频 | 福利色在线播放 | 大黑屌视频 |