Master Java Object Mapping: VO, BO, DTO, PO with Simple Object Copy

This article explains the different POJO variants—VO, BO, PO, DTO, and DO—describes their typical usage in layered Java applications, introduces the Simple Object Copy IntelliJ plugin for one‑click conversion method generation, compares it with common mapping tools such as MapStruct and BeanUtils, and discusses performance and flexibility advantages.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Master Java Object Mapping: VO, BO, DTO, PO with Simple Object Copy

In Java projects a POJO (Plain Old Java Object) can be classified into several roles:

VO (View Object) : objects returned to the front‑end for display.

BO (Business Object) : objects used inside the service layer to encapsulate business logic.

PO (Persistent Object) : objects that directly map to database tables and hold persisted data.

DTO (Data Transfer Object) : objects transferred between services or layers to decouple components.

DO (Domain Object) : in Alibaba's manual it is equivalent to PO, while in Domain‑Driven Design it corresponds to BO.

Typical conversion flow: DTO → BO (service layer) → VO (controller layer) → front‑end. The following reference documents provide more details:

https://juejin.cn/post/6952848675924082718
https://juejin.cn/post/6844904046097072141
https://zhuanlan.zhihu.com/p/264675395

Simple Object Copy Plugin

The IntelliJ IDEA plugin Simple Object Copy generates conversion methods between objects with a single shortcut (Alt+Insert on Windows or ⌘+N on macOS). No manual code is required for simple field copying.

Example of a generated conversion method for UserVO:

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

Generated code screenshots:

Generated method view
Generated method view
Complex object conversion view
Complex object conversion view

Comparison with Other Mapping Tools

Common Java mapping utilities include:

Spring BeanUtils (copyProperties)

Cglib BeanCopier (copyProperties)

Apache BeanUtils (copyProperties)

Apache PropertyUtils (copyProperties)

Dozer

MapStruct

JSON serialization + deserialization

These tools require adding external dependencies and invoking specific APIs. They often rely on reflection or proxies, which can cause performance overhead and make the code harder to read. Missing or renamed fields usually require additional manual mapping code.

MapStruct Example

@Mapper(componentModel = "spring", uses = {RoleVOMapper.class, RoomVOMapper.class})
public interface UserMapper {
    UserVO toUserVO(UserDTO userDTO);
}

@Mapper(componentModel = "spring")
public interface RoleMapper {
    RoleVO toRoleVO(RoleDTO roleDTO);
}

@Mapper(componentModel = "spring")
public interface RoomMapper {
    RoomVO toRoomVO(RoomDTO roomDTO);
}

When the source DTO lacks fields such as roomName or buildingName, MapStruct requires extra mapping methods, and the compiler will not warn about the missing fields.

BeanUtils Example

@Data
public class UserVO {
    // fields omitted for brevity
    public static UserVO convertToUserVO(UserDTO item) {
        if (item == null) {
            return null;
        }
        UserVO result = new UserVO();
        BeanUtils.copyProperties(item, result);
        // manual handling of nested objects and missing fields
        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;
    }
}

BeanUtils uses reflection, which leads to slower performance and does not generate compile‑time checks for missing fields.

Performance and Flexibility

Simple Object Copy generates plain setter calls, avoiding reflection and proxy generation, resulting in a performance advantage that is an order of magnitude better than the reflective approaches. It also creates empty methods for fields that do not exist in the source object, prompting developers to fill them and preventing silent null values.

Other Useful Plugins

Another handy plugin is generateAllSetter , which can be used together with Simple Object Copy to generate all setter methods automatically.

Installation

Open IntelliJ IDEA, go to the Plugins marketplace, search for “Simple Object Copy”, and install it.

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.

JavaCode GenerationBeanUtilsmapstructObject MappingIDE pluginpojo
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.