美文网首页
初识DO,DTO,VO

初识DO,DTO,VO

作者: _果不其然_ | 来源:发表于2018-10-23 23:17 被阅读0次

    在日常的项目开发中,VO对应于页面上需要显示的数据(表单),DO对应于数据库中存储的数据(数据表),DTO对应于除二者之外需要进行传递的数据。

    • DO(Domain Object)

    领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。

    • DTO(Data Transfer Object):

    数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。

    • VO(View Object):

    视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。

    下面以一个时序图建立简单模型来描述上述对象在三层架构应用中的位置

    image.png
    • 用户发出请求(可能是填写表单),表单的数据在展示层被匹配为VO。

    • 展示层把VO转换为服务层对应方法所要求的DTO,传送给服务层。

    • 服务层首先根据DTO的数据构造(或重建)一个DO,调用DO的业务方法完成具体业务。

    • 服务层把DO转换为持久层对应的PO(可以使用ORM工具,也可以不用),调用持久层的持久化方法,把PO传递给它,完成持久化操作。

    • 对于一个逆向操作,如读取数据,也是用类似的方式转换和传递。

    我们通过一个demo理解一下这几个概念:

    假如我们的项目中由User这样一个实体。我们在创建User表的时候一般包含一下属性:

    image

    java类

    public  class  UserDO {
        private  Integer id;                 //唯一主键
        private  Date  createdTime;           //创建时间
        private  Date  updatedTime;           //最后更新时间
        private  String  name;                //姓名
        private  Integer age;                //年龄
        private  String  gender;              //性别
        private  String  address;             //住址
        private  String  password;            //密码
        private  String  nickName;            //昵称
        private  Date  birthday;              //生日
        private  String  politicalStatus;     //政治面貌,1表示群众,2表示团员,3表示党员,4表示其他,100表示未知
        private  Integer  companyId;          //公司的ID
        private  Integer status;             //数据状态,1表示可用,0表示不可用
    }
    

    然后,在代码中,从DAO一直到前端展示,我们都通过这个UserDO类的对象来进行数据传输。这样做会有什么问题嘛?

    • 不需要的字段也会传递到前端页面。
    • 如password、createdTime、updatedTime和status这几个字段我们可能在前端根本不需要展示,但是这些字段有可能也会被传递到前端(除非我们在SQL查询的时候没有查询出对应的字段)。这不仅使数据的传输量增大,还可能有安全性问题。
    • 某些字段需要转换,但是无法支持。
    • 对于上面例子中的政治面貌字段,我们在数据库中存储的是数字,但是在前端页面我要展示的是中文描述。这种情况只能在前端通过if/else的方式来分情况展示。
    • 某些字段要展示,但是并不希望出现在数据库中
    • 在User表中我们只保存了这个用户的companyId,需要同时查询company表来查询出该公司的更多详细信息。对于User对象,如果我们想在前端同时展示他所属的公司,希望通过一次查询全都查出来怎么办?有几个简单的方案,第一个是让UserDO中包含一个Company类的属性,通过这个属性来传递。另外一种是把我们希望传到前端的Company的属性也写到UserDO中。但是,如果真的这么做了,那UserDO还能被称作DO了吗?

    可见,使用一个DO从头用到尾(从数据库到前端页面)并不是一种好的设计。

    如何正确的使用DO、DTO、VO

    对于上面的例子,我们可以将他设计成以下类。由于模型并不复杂,这里只需要再引入VO就可以了。

    引入UserVO,用于封装传递到前端需要展示的字段。

    public  class  UserVO {
        private  Integer id;                 //唯一主键
        private  String name;                //姓名
        private  Integer age;                //年龄
        private  String gender;              //性别
        private  String address;             //住址
        private  String nickName;            //昵称
        private  Date birthday;              //生日
        private  String education;           //学历
        private  String politicalStatus;     //政治面貌,群众、团员、党员等
        private  Company company;            //公司
    }
    

    总结

    UserDO和UserVO中包含了大量的相同字段。不过真的有必要再单独设计个VO吗?我可以明确告诉你的是,当你的系统越来越大,表中的字段越来越多的时候,使用DO\DTO\VO等概念进行分层处理是绝对有好处的。

    相关文章

      网友评论

          本文标题:初识DO,DTO,VO

          本文链接:https://www.haomeiwen.com/subject/jadwzftx.html