POJO 的定義是無(wú)規(guī)則簡(jiǎn)單的對(duì)象,在日常的代碼分層中 pojo 會(huì)被分為VO、BO、 PO、 DTOVO (view object/value object)表示層對(duì)象1、前端展示的數(shù)據(jù),在接口數(shù)據(jù)返回給前端的時(shí)候需要轉(zhuǎn)成VO2、個(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ù),用來(lái)存儲(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來(lái)解耦DO(domain object)領(lǐng)域?qū)嶓w對(duì)象①阿里巴巴的開(kāi)發(fā)手冊(cè)中的定義,DO( Data Object)這個(gè)等同于上面的PO②DDD(Domain-Driven Design)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中,DO(Domain Object)這個(gè)等同于上面的BOhttps://juejin.cn/post/6952848675924082718 https://juejin.cn/post/6844904046097072141 https://zhuanlan.zhihu.com/p/264675395
1. 定義方法出入?yún)?/p> 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<RoleVO> 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<RoleDTO> 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<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.無(wú)入侵市面上有很多類似的工具類,比較常用的有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í)體中不存在的屬性,沒(méi)有提示,小心前端總是問(wèn)為啥都是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("尚德樓"); } } 不支持復(fù)雜對(duì)象還是要寫大量代碼,代碼字段不清晰不易理解,別人接手難。RoomDTO中不存在的roomName、buildingName還要BeanUtils另寫方法,很容易忽略。源實(shí)體中不存在的屬性,沒(méi)有提示,小心前端總是問(wèn)為啥都是null。@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 == null) { return null; } UserVO result = new UserVO(); BeanUtils.copyProperties(item,result); List<RoleDTO> 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; } } 相比上面的工具類,不是使用反射、就是是用代理、序列化操作。相比于純正的set方法去轉(zhuǎn)化,差距不是一個(gè)量級(jí)。此次不贅述。跟上述工具類相比插件有很大優(yōu)勢(shì),不再贅述,下面我們比較一下,我之前常用的idea插件generateO2O 在此推薦其他一個(gè)我常用插件:generateAllSetter,搭配食用更佳,打開(kāi)idea plugins,切market place 搜索:Simple Object Copy
來(lái)源:juejin.cn/post/7053264631262871583
|