Stop Confusing PO, VO, BO, DTO, DAO, and POJO: A Complete Guide
This article explains the six common Java object types—POJO, PO, DAO, BO, DTO, and VO—detailing their roles in a three‑layer architecture, how they flow through a request, conversion tools, a comparison table, and answers common questions for developers.
Overall Structure
In a typical three‑layer (or MVC) architecture, data flows from the database to the user interface through distinct stages: the persistence layer maps fields, the business layer applies logic, and the presentation layer formats data for the front end. Each stage uses a dedicated object type to avoid a single class shouldering all responsibilities.
The diagram shows each layer’s object responsibilities: VO for the front end, BO and DTO for business logic and data transfer, PO and DAO for persistence, and POJO as the plain Java base.
1. POJO – Plain Old Java Object
Plain Old Java Object
A POJO is a clean Java class with fields and getters/setters that does not depend on any framework—no @Entity, no implements Serializable, no specific base class.
public class User {
private Long id;
private String name;
private String email;
// getter / setter
}All other object types extend POJO: PO adds ORM annotations, DTO adds serialization, VO tailors fields for display. Compared with JavaBean, POJO has looser requirements.
2. PO – Persistent Object
Persistent Object
PO represents a database record. For a user table you create a UserPO class whose fields map one‑to‑one to the table columns.
@Entity
@Table(name = "user")
public class UserPO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username")
private String username;
@Column(name = "password")
private String password;
@Column(name = "create_time")
private LocalDateTime createTime;
// getter / setter
}PO’s lifecycle matches the database record; it carries no business logic. In JPA/Hibernate projects PO carries @Entity and @Table; in MyBatis the model class is a clean POJO with XML mapping.
Common pitfall: never return PO directly to the front end, as it may expose sensitive fields and tightly couple the front end to database schema changes.
3. DAO – Data Access Object
Data Access Object
DAO is an interface that encapsulates database operations, hiding SQL or ORM details from the business layer.
public interface UserDAO extends JpaRepository<UserPO, Long> {
UserPO findByUsername(String username);
List<UserPO> findByStatus(Integer status);
}MyBatis equivalent:
public interface UserMapper {
UserPO selectById(Long id);
int insert(UserPO user);
int updateStatus(@Param("id") Long id, @Param("status") Integer status);
void deleteById(Long id);
}DAO acts as the “front desk” of the database, allowing business code to request data without knowing storage details. This isolation makes it easy to switch databases (e.g., MySQL to PostgreSQL) without changing business logic.
4. BO – Business Object
Business Object
BO works in the Service layer. It may combine multiple PO objects and contain business methods.
public class UserBO {
private UserPO user;
private List<RolePO> roles;
// business methods
public boolean isAdmin() {
return roles.stream().anyMatch(r -> "ADMIN".equals(r.getCode()));
}
public boolean canPlaceOrder() {
return user.getStatus() == 1 && user.getBalance().compareTo(BigDecimal.ZERO) > 0;
}
}In some projects BO is the Service class itself; the core idea is that BO carries business logic.
5. DTO – Data Transfer Object
Data Transfer Object
DTO’s sole responsibility is to transport data between layers or services. It usually implements Serializable for network transmission and should be flat, without complex nested objects or business methods.
public class UserDTO implements Serializable {
private static final long serialVersionUID = 1L;
private Long userId;
private String userName;
private String email;
// getter / setter
}In micro‑service architectures DTOs are heavily used to decouple services and avoid exposing internal database structures.
Common confusion: some teams call request‑parameter objects DTOs (e.g., CreateUserDTO); the key is to keep the naming consistent within the team.
6. VO – Value Object
Value Object
VO is tailored for front‑end display. Its fields and formats are designed according to front‑end needs, not database or business logic.
public class UserVO {
private Long id;
private String name;
private String avatar;
private String statusText; // e.g., "Normal" or "Banned"
private String registerDate; // formatted date string
// getter / setter
}VO may contain formatted strings (e.g., statusText, registerDate) that are derived in Service or Controller layers, keeping PO clean.
VO vs. DTO: DTO emphasizes transport across layers/services; VO emphasizes presentation to the front end.
7. Object Conversion Chain
Typical request flow (e.g., “query user info”):
Front end sends request to Controller, possibly wrapping parameters in a DTO.
Controller calls Service, which invokes DAO to fetch a PO.
Service converts PO to BO to execute business rules.
BO is transformed into a DTO for return (or for inter‑service calls).
Controller converts DTO to VO and returns it to the front end.
Steps 4 and 5 can be merged in some projects; the exact granularity depends on team conventions.
Conversion Tools
Hand‑written conversion code is error‑prone. Recommended tools:
MapStruct : compile‑time generated, type‑safe, high‑performance mapper.
@Mapper
public interface UserConverter {
UserConverter INSTANCE = Mappers.getMapper(UserConverter.class);
@Mapping(source = "userId", target = "id")
@Mapping(source = "userName", target = "name")
UserVO toVO(UserDTO dto);
} BeanUtils.copyProperties: shallow copy only; risky when field names differ.
Comparison of Object Types
POJO – Plain Old Java Object; no framework dependency; base for all other types.
PO – Persistent Object; resides in the persistence layer; maps one‑to‑one to a database table; contains no business logic.
DAO – Data Access Object; resides in the persistence layer; encapsulates CRUD operations; isolates SQL/ORM details.
BO – Business Object; resides in the business layer; encapsulates business logic; may combine multiple PO instances.
DTO – Data Transfer Object; used between layers or services; flat structure, implements Serializable, contains no business methods.
VO – Value Object; resides in the presentation layer; designed for front‑end consumption; may include formatted or computed fields.
Frequently Asked Questions
Q: Is this granularity necessary for small projects? Not always. For projects with fewer than five tables, PO can be used directly as VO and DAO calls can be placed in Service without extra layers. The system is designed for large‑scale maintainability.
Q: Can VO and DTO be merged? Yes. Many REST APIs return DTO directly as the response, effectively using it as VO. As long as the team agrees on conventions, it’s acceptable. Strict separation is more valuable in micro‑service environments.
Q: What is DO (Domain Object) and how does it relate to PO? DO is a DDD term representing a domain entity that often contains business logic, similar to BO. PO is purely a database mapping object. In DDD, conversion between DO and PO is common.
Conclusion
The six concepts embody a simple principle: let each object do only what it should do . PO and DAO handle persistence, BO handles business logic, DTO moves data, VO presents to the front end, and POJO serves as the common foundation. These naming conventions are an industry‑wide engineering consensus rather than official Java standards. Understanding each layer’s focus helps choose the right object type and avoid confusion when encountering many similarly named classes.
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.
