一款 IDEA 插件帮你优雅转化 DTO、VO、BO、PO、DO

x33g5p2x  于2022-04-16 转载在 其他  
字(5.4k)|赞(0)|评价(0)|浏览(724)

POJO 的定义是无规则简单的对象,在日常的代码分层中 pojo 会被分为VO、BO、 PO、 DTO

VO (view object/value object)表示层对象

1、前端展示的数据,在接口数据返回给前端的时候需要转成VO

2、个人理解使用场景,接口层服务中,将DTO转成VO,返回给前台

B0(bussines object)业务层对象

1、主要在服务内部使用的业务对象

2、可以包含多个对象,可以用于对象的聚合操作

3、个人理解使用场景,在服务层服务中,由DTO转成BO然后进行业务处理后,转成DTO返回到接口层

PO(persistent object)持久对象

1、出现位置为数据库数据,用来存储数据库提取的数据

2、只存储数据,不包含数据操作

3、个人理解使用场景,在数据库层中,获取的数据库数据存储到PO中,然后转为DTO返回到服务层中

DTO(Data Transfer Object)数据传输对象

1、在服务间的调用中,传输的数据对象

2、个人理解,DTO是可以存在于各层服务中(接口、服务、数据库等等)服务间的交互使用DTO来解耦

DO(domain object)领域实体对象

DO 现在主要有两个版本:

①阿里巴巴的开发手册中的定义,DO( Data Object)这个等同于上面的PO

②DDD(Domain-Driven Design)领域驱动设计中,DO(Domain Object)这个等同于上面的BO

参考文档:

  1. https://juejin.cn/post/6952848675924082718
  2. https://juejin.cn/post/6844904046097072141
  3. https://zhuanlan.zhihu.com/p/264675395

插件名称:Simple Object Copy

  1. 定义方法出入参

  2. 光标定位方法内,使用快捷键ALT+INSERT(WIN) 、 command + N(mac) ,或者右键鼠标选择Generate,弹出生成选项框后,选择genCopyMethod,代码就生成好了

需要手写的代码

一键生成后的展示

复杂对象转化展示(一键生成后的展示)

复杂对象转化源码示例

  1. @Data
  2. public class UserVO {
  3.     private String name;
  4.     private Date entryDate;
  5.     private String userId;
  6.     private List<RoleVO> roleList;
  7.     private RoomVO room;
  8.     public static UserVO convertToUserVO(UserDTO item) {
  9.         if (item == null) {
  10.             return null;
  11.         }
  12.         UserVO result = new UserVO();
  13.         result.setName(item.getName());
  14.         result.setEntryDate(item.getEntryDate());
  15.         result.setUserId(item.getUserId());
  16.         List<RoleDTO> roleList = item.getRoleList();
  17.         if (roleList == null) {
  18.             result.setRoleList(null);
  19.         } else {
  20.      result.setRoleList(roleList.stream().map(UserVO::convertToRoleVO).collect(Collectors.toList());
  21.         }
  22.         result.setRoom(convertToRoomVO(item.getRoom()));
  23.         return result;
  24.     }
  25.     public static RoomVO convertToRoomVO(RoomDTO item) {
  26.         if (item == null) {
  27.             return null;
  28.         }
  29.         RoomVO result = new RoomVO();
  30.         result.setRoomId(item.getRoomId());
  31.         result.setBuildingId(item.getBuildingId());
  32.         result.setRoomName();
  33.         result.setBuildingName();
  34.         return result;
  35.     }
  36.     public static RoleVO convertToRoleVO(RoleDTO item) {
  37.         if (item == null) {
  38.             return null;
  39.         }
  40.         RoleVO result = new RoleVO();
  41.         result.setRoleId(item.getRoleId());
  42.         result.setRoleName(item.getRoleName());
  43.         result.setCreateTime(item.getCreateTime());
  44.         return result;
  45.     }
  46. }
  47. @Data
  48. public class UserDTO {
  49.     private String name;
  50.     private Date entryDate;
  51.     private String userId;
  52.     private List<RoleDTO> roleList;
  53.     private RoomDTO room;
  54. }
  55. @Data
  56. public class RoleVO {
  57.     private String roleId;
  58.     private String roleName;
  59.     private LocalDateTime createTime;
  60. }
  61. @Data
  62. public class RoleDTO {
  63.     private String roleId;
  64.     private String roleName;
  65.     private LocalDateTime createTime;
  66. }
  67. @Data
  68. public class RoomVO {
  69.     private String roomId;
  70.     private String buildingId;
  71.     private String roomName;
  72.     private String buildingName;
  73. }
  74. @Data
  75. public class RoomDTO {
  76.     private String roomId;
  77.     private String buildingId;
  78. }

1.无入侵市面上有很多类似的工具类,比较常用的有

1、Spring BeanUtils (copyProperties)

2、Cglib  BeanCopier (copyProperties)

3、Apache BeanUtils (copyProperties)

4、Apache PropertyUtils (copyProperties)

5、Dozer

6、mapstruct

7、JSON 序列化 再反序列化

这些工具,不仅要引入相应的依赖jar包,而且对代码有入侵,要调用对应得api方法才能进行转化,一旦遇到类型不一致,字段名稍有变动,就需要另写java代码补全字段,整体代码非常丑陋。

举例:

1. mapstruct

同样的代码,,不仅要引入依赖、写如下转化mapper,还要,在对应地方调用对应api(代码入侵验证),然而Simple Object Copy 只需要一键生成。

RoomDTO中不存在的roomName、buildingName还要mapstruct另写方法,很容易忽略。源实体中不存在的属性,没有提示,小心前端总是问为啥都是null。

在Simple Object Copy 插件代码生成后,不存在的字段也生成了空方法,直接编译提示补充,不容易忽略

需要手写的代码

  1. @Mapper(componentModel = "spring",uses = {RoleVOMapper.class,RoomVOMapper.class})
  2. public interface UserMapper {
  3.     UserConverter INSTANCE = Mappers.getMapper(UserConverter.class);
  4.     
  5.     UserVO toUserVO(UserDTO userDTO);
  6. }
  7. @Mapper(componentModel = "spring")
  8. public interface RoleMapper {
  9.     RoleVO toRoleVO(RoleDTO roleDTO);
  10. }
  11. @Mapper(componentModel = "spring")
  12. public interface RoomMapper {
  13.     RoomVO toRoomVO(RoomDTO roomDTO);
  14. }
  15. public class Main {
  16.     public static void main(String[] args) {
  17.         UserDTO user = ;
  18.         UserVO userVO = UserMapper.INSTANCE.toUserVO(user);
  19.         userVO.getRoomVO().setRoomName("大厅1");
  20.         userVO.getRoomVO().setBuildingName("尚德楼");
  21.     }
  22. }

1. BeanUtils

性能稍差。

不支持复杂对象还是要写大量代码,代码字段不清晰不易理解,别人接手难。RoomDTO中不存在的roomName、buildingName还要BeanUtils另写方法,很容易忽略。源实体中不存在的属性,没有提示,小心前端总是问为啥都是null。

需要手写的代码

  1. @Data
  2. public class UserVO {
  3.     private String name;
  4.     private Date entryDate;
  5.     private String userId;
  6.     private List<RoleVO> roleList;
  7.     private RoomVO room;
  8.     public static UserVO convertToUserVO(UserDTO item) {
  9.         if (item == null) {
  10.             return null;
  11.         }
  12.         UserVO result = new UserVO();
  13.         BeanUtils.copyProperties(item,result);
  14.         List<RoleDTO> roleList = item.getRoleList();
  15.         if (roleList == null) {
  16.             result.setRoleList(null);
  17.         } else {
  18.      result.setRoleList(roleList.stream().map(UserVO::convertToRoleVO).collect(Collectors.toList());
  19.         }
  20.         result.setRoom(convertToRoomVO(item.getRoom()));
  21.         return result;
  22.     }
  23.     public static RoomVO convertToRoomVO(RoomDTO item) {
  24.         if (item == null) {
  25.             return null;
  26.         }
  27.         RoomVO result = new RoomVO();
  28.         BeanUtils.copyProperties(item,result);
  29.         
  30.         result.setRoomName();
  31.         result.setBuildingName();
  32.         return result;
  33.     }
  34.     public static RoleVO convertToRoleVO(RoleDTO item) {
  35.         if (item == null) {
  36.             return null;
  37.         }
  38.         RoleVO result = new RoleVO();
  39.         BeanUtils.copyProperties(item,result);
  40.         return result;
  41.     }
  42. }

2.性能优势

相比上面的工具类,不是使用反射、就是是用代理、序列化操作。相比于纯正的set方法去转化,差距不是一个量级。此次不赘述。

3.灵活性、兼容性

跟上述工具类相比插件有很大优势,不再赘述,下面我们比较一下,我之前常用的idea插件generateO2O

在此推荐其他一个我常用插件:generateAllSetter,搭配食用更佳,

4. 如何下载?

打开idea plugins,切market place 搜索:Simple Object Copy

来源:juejin.cn/post/7053264631262871583

推荐3个原创springboot+Vue项目,有完整视频讲解与文档和源码:

【dailyhub】【实战】带你从0搭建一个Springboot+elasticsearch+canal的完整项目
  • 视频讲解:https://www.bilibili.com/video/BV1Jq4y1w7Bc/
  • 完整开发文档:https://www.zhuawaba.com/post/124
  • 线上演示:https://www.zhuawaba.com/dailyhub
【VueAdmin】手把手教你开发SpringBoot+Jwt+Vue的前后端分离后台管理系统
  • 视频讲解:https://www.bilibili.com/video/BV1af4y1s7Wh/
  • 完整开发文档前端:https://www.zhuawaba.com/post/18
  • 完整开发文档后端:https://www.zhuawaba.com/post/19
  • 线上演示:https://www.markerhub.com/vueadmin/
【VueBlog】基于SpringBoot+Vue开发的前后端分离博客项目完整教学
  • 视频讲解:https://www.bilibili.com/video/BV1PQ4y1P7hZ
  • 完整开发文档:https://www.zhuawaba.com/post/17

关注我,学Java

相关文章