一款 IDEA 插件幫你優雅轉化 DTO、VO、BO、PO、DO

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

參考文檔:

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

插件名稱:Simple Object Copy

  1. 定義方法出入參

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

需要手寫的代碼

一鍵生成後的展示

複雜對象轉化展示(一鍵生成後的展示)

複雜對象轉化源碼示例

@Data
public class UserVO {
private String name;
private Date entryDate;
private String userId;
private List<RoleVO> roleList;
private RoomVO room;
public static UserVO convertToUserVO(UserDTO item) {
if (item == ) {
return ;
}UserVO result = new UserVO;

result.setName(item.getName);result.setEntryDate(item.getEntryDate);result.
setUserId(item.getUserId);List<RoleDTO> roleList = item.getRoleList;if (roleList == ) {
result.setRoleList;} 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 == ) {
return ;
}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 == ) {
return ;
}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<RoleDTO> 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 序列化 再反序列化

這些工具,不僅要引入相應的依賴 jar 包, 而且對代碼有入侵,要調用對應得 api 方法才能進行轉化,一旦遇到類型不一致,字段名稍有變動,就需要另寫 java 代碼補全字段,整體代碼非常醜陋。

舉例:

  1. mapstruct

同樣的代碼,,不僅要引入依賴、寫如下轉化 mapper,還要,在對應地方調用對應 api(代碼入侵驗證),然而 Simple Object Copy 只需要一鍵生成。

RoomDTO 中不存在的 roomName、buildingName 還要 mapstruct 另寫方法,很容易忽略。源實體中不存在的屬性,沒有提示,小心前端總是問爲啥都是。

在 Simple Object Copy 插件代碼生成後,不存在的字段也生成了空方法,直接編譯提示補充,不容易忽略

需要手寫的代碼

@Mapper(componentModel = "spring",uses = {RoleVOMapper.class,RoomVOMapper.class})
publicinterfaceUserMapper{
UserConverter INSTANCE = Mappers.getMapper(UserConverter.class);
UserVO toUserVO(UserDTO userDTO);
}@Mapper(componentModel = "spring")
publicinterfaceRoleMapper{
RoleVO toRoleVO(RoleDTO roleDTO);
}@Mapper(componentModel = "spring")
publicinterfaceRoomMapper{
RoomVO toRoomVO(RoomDTO roomDTO);
}publicclassMain{
publicstaticvoidmain(String[] args) {
UserDTO user = ;UserVO userVO = UserMapper.INSTANCE.toUserVO(user);userVO.getRoomVO.setRoomName("大廳1");
userVO.getRoomVO.setBuildingName("尚德樓");
}}

1. BeanUtils

性能稍差。

不支持複雜對象還是要寫大量代碼,代碼字段不清晰不易理解,別人接手難。RoomDTO 中不存在的 roomName、buildingName 還要 BeanUtils 另寫方法,很容易忽略。源實體中不存在的屬性,沒有提示,小心前端總是問爲啥都是。

需要手寫的代碼

@Data
publicclassUserVO{
private String name;
private Date entryDate;
private String userId;
private List<RoleVO> roleList;
private RoomVO room;
public static UserVO convertToUserVO(UserDTO item) {
if (item == ) {
return ;
}UserVO result = new UserVO;

BeanUtils.copyProperties(item,result);List<RoleDTO> roleList =
 item.getRoleList;if (roleList == ) {
result.setRoleList;} 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 == ) {
return ;
}RoomVO result = new RoomVO;

BeanUtils.copyProperties(item,result);result.setRoomName;result.setBuildingName;
return result;
}public static RoleVO convertToRoleVO(RoleDTO item) {
if (item == ) {
return ;
}RoleVO result = new RoleVO;
BeanUtils.copyProperties(item,result);return result;
}}

2. 性能優勢

相比上面的工具類,不是使用反射、就是是用代理、序列化操作。相比於純正的 set 方法去轉化,差距不是一個量級。此次不贅述。

3. 靈活性、兼容性

跟上述工具類相比插件有很大優勢,不再贅述,下面我們比較一下,我之前常用的 idea 插件 generateO2O

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

4. 如何下載?

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

來源:

juejin.cn/post/7053264631262871583

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Q-JN1VELq8qxhO0OdRPNMw