Simple Object Copy,一款idea插件帮你优雅转化DTO、VO、BO、PO、DO

1、什么是DTO、VO、BO、PO、DO、POJO

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

2、插件如何完成转化

插件名称:Simple Object Copy

  1. 定义方法出入参

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

需要手写的代码

e14749988453e8502ca89eafc4d0719c.png

一键生成后的展示

bab5efb48dbaf826fa90cb60604cb82a.png

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

276041957-61e36d10b9f86_fix732.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;

}

3、其他转化方式

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);

        //这里没有代码提示,需要自己写,小心前端总是问为啥都是null

        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

| 我方插件 | 特点 | 对比插件 | 特点 |

| --- | --- | --- | --- |

| Simple Object Copy | 依据返回值为主,根据字段名去匹配 ,不会导致返回值漏属性 | generateO2O | 以入参为主匹配字段,存在漏属性的情况 |

| Simple Object Copy | 支持对象包含对象、对象包含list、set集合的转化 | generateO2O | 不支持子对象的转化、不支持list泛型不同的转化 |

| Simple Object Copy | 相同出入参类名,生成全限定类名 | generateO2O | 同类名出现问题 |

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

4、如何下载

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

[图片上传失败...(image-68d0ea-1644312057100)]

试用30天,支付宝、微信、PayPal都可以付款。 6元(人民币)每年,当然学生、教育机构、公益免费。

官方会邮件让你注册jb账号,给账号开通权限,你可以在官网找到自己的激活码,然后再idea 不登录用。也可以在idea 登录jb账号在线试用。

这可能是你的第一个付费插件。多谢支持,哈哈!

如果你没钱的话,也可邮件我。我找找有没有免费方式。

下班早一半

通过插件的使用

1、可以节省一个个字段的设置的开发时间

2、避免了漏字段设置,ps:前端同学总是来问为啥字段总是null

3、而且通过出入参的设计思想去开发,规范了代码,在有特殊请求转化的时候也比较方便。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容