Understanding DTO, BO, PO, and VO in Backend Development
This article explains the differences between DTO, BO, PO, and VO in backend development, illustrates their roles with Java code examples, and shows how to configure global settings to filter null fields in DTOs, reducing the need for separate VO objects.
In backend development, especially within MVC and DDD architectures, several object types are commonly used: DTO (Data Transfer Object), BO (Business Object), PO (Persistent Object), and VO (Value Object).
DTO is used to transfer data between services or from server to client, containing only the data needed for a specific business scenario without business logic, thus reducing coupling.
BO represents objects in the business logic layer, encapsulating data related to a business operation along with the operations on that data; a BO may consist of multiple entity attributes and handle complex logic.
PO maps directly to a database table record, with fields corresponding to table columns, and is typically used in the persistence layer (e.g., Hibernate, JPA) for CRUD operations.
VO is a view‑layer object used to present data to the user; it may correspond to a database table or be tailored to UI requirements, aiming to expose only necessary data.
Example Java classes illustrate these concepts:
@Data
public class User implements Serializable {
private Long id;
private String username;
private String password;
private String identityCard;
private String gender;
private String location;
private String userImage;
private String phoneNumber;
private String createTime;
private String updateTime;
@TableLogic
private int isDelete;
} @Data
public class UserDTO implements Serializable {
private Long id;
private String username;
private String password;
private String identityCard;
private String gender;
private String location;
private String userImage;
private String phoneNumber;
} @Data
public class UserLoginBO implements Serializable {
private String username;
private String password;
}
@Data
public class UserUpdateBO implements Serializable {
private Long id;
private String username;
private String password;
private String identityCard;
private String gender;
private String location;
private String userImage;
private String phoneNumber;
}The article notes that a UserDTO serves as a large entry point receiving module parameters, while BO filters and controls data before it reaches the Service layer, and finally the data is transformed into a PO before persisting.
It also mentions that VO is often unnecessary because DTOs can be configured to omit null fields, eliminating the need for a separate view object.
To globally filter null values in DTOs, the following Spring configuration can be used:
@Configuration
public class GlobalConfig extends WebMvcConfigurationSupport {
@Override
protected void configureMessageConverters(List
> converters) {
super.configureMessageConverters(converters);
converters.add(mappingJackson2HttpMessageConverter());
}
/**
* Custom MappingJackson2HttpMessageConverter
* Currently implements: ignore null values, allow empty fields
*/
private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
return new MappingJackson2HttpMessageConverter(objectMapper);
}
}This configuration ensures that null fields are not serialized, effectively achieving the same result that a separate VO would provide.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
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.