Understanding POJO Types (VO, BO, PO, DTO, DO) and Using the Simple Object Copy Plugin for Java Object Mapping
This article explains the different POJO classifications such as VO, BO, PO, DTO and DO, describes their typical usage scenarios in layered Java applications, and demonstrates how the Simple Object Copy IntelliJ plugin can automatically generate conversion code, comparing it with other mapping tools.
POJO (Plain Old Java Object) is a simple, rule‑less object that is often divided into several specialized forms in a typical layered architecture: VO, BO, PO, DTO, and DO.
VO (View Object/Value Object) is used at the presentation layer; data returned to the front‑end is converted into a VO, usually by transforming a DTO in the service layer.
BO (Business Object) lives inside the service layer, may aggregate multiple objects, and is created from a DTO for business processing before being turned back into a DTO for the API layer.
PO (Persistent Object) represents data stored in the database; it only holds data without any business logic and is converted from PO to DTO when passing data upward.
DTO (Data Transfer Object) is used for data exchange between services or layers, helping to decouple components.
DO (Domain Object) has two meanings: in Alibaba’s development manual it is equivalent to PO, while in Domain‑Driven Design it corresponds to BO.
The article introduces the IntelliJ plugin Simple Object Copy , which can generate conversion methods with a single shortcut (Alt+Insert or ⌘N). After generation, the plugin also creates empty methods for missing fields, prompting developers to implement them.
Example of generated conversion code:
@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;
}Compared with other mapping solutions such as Spring BeanUtils, Cglib BeanCopier, Apache BeanUtils, Dozer, MapStruct, and JSON serialization, the plugin is non‑intrusive (no additional dependencies or API calls) and automatically generates stubs for missing fields, reducing the risk of null values.
MapStruct, for example, requires a mapper interface and explicit method definitions, and developers must manually handle fields that do not exist in the source class. Simple Object Copy generates empty methods for those fields, prompting immediate implementation.
Other tools like BeanUtils rely on reflection, which can be slower and still need custom handling for complex objects, making the generated code harder to read and maintain.
The plugin also offers performance advantages because it avoids reflection or proxy generation, using straightforward setter calls instead.
For flexibility and compatibility, the article compares Simple Object Copy with another popular plugin generateO2O and recommends using generateAllSetter together for an even smoother development experience.
To install Simple Object Copy, open IntelliJ IDEA's plugin marketplace, search for “Simple Object Copy”, and install it.
Source: 码猿技术专栏
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.