一款 IDEA 插件帮你优雅转化 DTO、VO、BO、PO、DO

POJO 的定义是无规则简单的对象,在日常的代码分层中 pojo 会被分为VO、BO、 PO、 DTO

VO (view object/value object)表示层对象

1、前端展示的数据,在接口数据返回给前端的时候需要转成VO

2、个人理解使用场景,接口层服务中,将DTO转成VO,返回给前台

B0(bussines object)业务层对象

1、主要在服务内部使用的业务对象

2、可以包含多个对象,可以用于对象的聚合操作

3、个人理解使用场景,在服务层服务中,由DTO转成BO然后进行业务处理后,转成DTO返回到接口层

PO(persistent object)持久对象

1、出现位置为数据库数据,用来存储数据库提取的数据

2、只存储数据,不包含数据操作

3、个人理解使用场景,在数据库层中,获取的数据库数据存储到PO中,然后转为DTO返回到服务层中

DTO(Data Transfer Object)数据传输对象

1、在服务间的调用中,传输的数据对象

2、个人理解,DTO是可以存在于各层服务中(接口、服务、数据库等等)服务间的交互使用DTO来解耦

DO(domain object)领域实体对象

DO 现在主要有两个版本:

①阿里巴巴的开发手册中的定义,DO( Data Object)这个等同于上面的PO

②DDD(Domain-Driven Design)领域驱动设计中,DO(Domain Object)这个等同于上面的BO

参考文档:

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

插件名称:Simple Object Copy

1. 定义方法出入参

2. 光标定位方法内,使用快捷键ALT+INSERT(WIN) 、 command + N(mac) ,或者右键鼠标选择Generate,弹出生成选项框后,选择genCopyMethod,代码就生成好了

需要手写的代码

9a268548e379424c2eddee4f168e55bd.png

一键生成后的展示

b6cecec45da98bef8efb6abeb7428268.png

复杂对象转化展示(一键生成后的展示)

708fcd6a89f434c949bd0df411594379.png

复杂对象转化源码示例

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

1.无入侵市面上有很多类似的工具类,比较常用的有

1、Spring BeanUtils (copyProperties)

2、Cglib  BeanCopier (copyProperties)

3、Apache BeanUtils (copyProperties)

4、Apache PropertyUtils (copyProperties)

5、Dozer

6、mapstruct

7、JSON 序列化 再反序列化

这些工具,不仅要引入相应的依赖jar包,而且对代码有入侵,要调用对应得api方法才能进行转化,一旦遇到类型不一致,字段名稍有变动,就需要另写java代码补全字段,整体代码非常丑陋。

举例:

1. mapstruct

同样的代码,,不仅要引入依赖、写如下转化mapper,还要,在对应地方调用对应api(代码入侵验证),然而Simple Object Copy 只需要一键生成。

RoomDTO中不存在的roomName、buildingName还要mapstruct另写方法,很容易忽略。源实体中不存在的属性,没有提示,小心前端总是问为啥都是null。

在Simple Object Copy 插件代码生成后,不存在的字段也生成了空方法,直接编译提示补充,不容易忽略

需要手写的代码

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

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

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


public class Main {
    public static void main(String[] args) {
        UserDTO user = ;
        UserVO userVO = UserMapper.INSTANCE.toUserVO(user);
        userVO.getRoomVO().setRoomName("大厅1");
        userVO.getRoomVO().setBuildingName("尚德楼");
    }
}

1. BeanUtils

性能稍差。

不支持复杂对象还是要写大量代码,代码字段不清晰不易理解,别人接手难。RoomDTO中不存在的roomName、buildingName还要BeanUtils另写方法,很容易忽略。源实体中不存在的属性,没有提示,小心前端总是问为啥都是null。

需要手写的代码

@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();
        BeanUtils.copyProperties(item,result);
        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();
        BeanUtils.copyProperties(item,result);
        
        result.setRoomName();
        result.setBuildingName();
        return result;
    }

    public static RoleVO convertToRoleVO(RoleDTO item) {
        if (item == null) {
            return null;
        }
        RoleVO result = new RoleVO();
        BeanUtils.copyProperties(item,result);
        return result;
    }
}

2.性能优势

相比上面的工具类,不是使用反射、就是是用代理、序列化操作。相比于纯正的set方法去转化,差距不是一个量级。此次不赘述。

3.灵活性、兼容性

跟上述工具类相比插件有很大优势,不再赘述,下面我们比较一下,我之前常用的idea插件generateO2O

f34067a03001d06753bfa439c16230a1.png

在此推荐其他一个我常用插件:generateAllSetter,搭配食用更佳,

4. 如何下载?

打开idea plugins,切market place 搜索:Simple Object Copy

066a56d7c2be126a3a39ce4aa3c6f7a0.png

来源:juejin.cn/post/7053264631262871583

b51ce3307e86f4a33d3a7f7cb9b09962.png

最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

明天见(。・ω・。)ノ♡

### VODTOBOPODOPOJO 的区别 #### 定义与特性 - **PO (Persistent Object)** 或者称为 **DO (Data Object)** 是用于表示持久化对象,通常与数据库中的表结构一一对应。这些类主要用于数据访问层(DAO),负责将业务实体映射到数据库记录上[^1]。 ```java public class UserPO { private Long id; private String name; } ``` - **VO (Value Object)** 表示值对象,在某些框架中也被称为传输对象(Transfer Object)。这类对象主要用来封装查询结果集或页面显示所需的数据集合。它们可以包含多个实体的信息组合而成的新视图模型[^3]。 ```java public class UserInfoVO { private String fullName; private int age; } ``` - **DTO (Data Transfer Object)** 主要目的是为了减少网络通信次数而设计的一种模式下的对象实例。当需要跨越不同进程空间传递大量复杂数据时使用此模式来简化接口定义并提高性能效率。 ```java public class UserDTO { private List<String> roles; private Address address; } ``` - **BO (Business Object)** 属于业务逻辑层面的对象,包含了具体的业务处理方法以及规则验证等功能模块。它不直接参与数据存储操作而是调用相应的 DAO 方法完成 CRUD 功能[^2]。 ```java public class UserServiceBO { public void registerUser(UserInfo info){ // business logic here... } } ``` - **POJO (Plain Old Java Object)** 则是一个非常简单的 Java 类型,没有任何特定继承关系或实现接口的要求。它可以被看作是最基础版本的 Bean 对象,仅提供 getter/setter 访问器函数即可满足需求[^4]。 ```java public class SimplePersonPOJO { private String firstName; public String getFirstName() {return this.firstName;} public void setFirstName(String value){this.firstName=value;} } ``` #### 使用场景分析 对于入参和出参的选择取决于具体的应用上下文: - 当从客户端接收请求参数时,应该优先考虑采用 `VO` 来接受前端传来的信息;而在返回响应给客户端之前,则应构建合适的 `VO` 将内部数据转换成易于理解的形式。 - 如果涉及到跨服务间的大规模数据交换,则建议利用 `DTO` 进行优化传输过程,从而降低不必要的开销。 - 在执行实际的增删改查动作前,应当先创建好对应的 `PO/DO` 实体以便后续存取数据库资源。 - 面向复杂的业务流程控制部分则交给 `BO` 处理更为合适,因为这里涉及到了更多关于领域知识的理解与运用。 - 至于那些只需要简单属性读写的场合下就可以放心大胆地选用 `POJO` 了!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值