Understanding DTO, BO, PO, VO: When and How to Use Each in Java Backend

This article explains the purpose and differences of DTO, BO, PO, and VO in Java backend development, shows concrete code examples, demonstrates how they fit into the request‑processing flow, and provides a global configuration to filter null fields before serialization.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Understanding DTO, BO, PO, VO: When and How to Use Each in Java Backend

Definitions

DTO (Data Transfer Object) – a plain object that carries data between layers or services. It contains only fields required for a specific use case and no business logic.

BO (Business Object) – an object in the business‑logic layer that may encapsulate multiple entities and contains validation or transformation logic before the data reaches the service layer.

PO (Persistent Object) – an object that maps one‑to‑one to a database table row. It is used by ORM frameworks (e.g., MyBatis, JPA) for CRUD operations.

VO (Value Object) – an object tailored for the view layer. It presents only the data needed by the client, often a subset or a reshaped version of the DTO.

Typical Java Class Illustrations

Persistent Object (PO) representing a user table:

@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 Transfer Object (DTO) used as the entry point for a module:

@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;
}

Business Objects (BO) that filter/validate data received from the DTO before the service layer:

@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;
}

Backend Flow Using DTO/BO/PO

Client sends a request → data is deserialized into UserDTO .

Controller converts UserDTO to a specific BO (e.g., UserLoginBO or UserUpdateBO ) to enforce business rules and boundary checks.

Service layer processes the BO and, before persisting, transforms it into a User PO that matches the database schema.

DAO/Mapper persists the PO.

Why a Separate VO May Be Omitted

If a DTO is configured to omit null fields during JSON serialization, the same DTO can be returned to the front‑end without exposing unwanted data. This reduces the need for an extra VO class.

Global Null‑Value Filtering Configuration (Spring MVC)

@Configuration
public class GlobalConfig extends WebMvcConfigurationSupport {

    @Override
    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.configureMessageConverters(converters);
        converters.add(mappingJackson2HttpMessageConverter());
    }

    /**
     * Custom MappingJackson2HttpMessageConverter that ignores null 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 any null property in a DTO is omitted from the JSON response, achieving the same effect as a dedicated VO.

Diagram showing DTO‑BO‑PO flow
Diagram showing DTO‑BO‑PO flow
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendDesign PatternsJavadtoPOvobo
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.