V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
itechnology
V2EX  ›  Java

关于 Java 中的 DO、DTO、BO、AO、VO、POJO 有没有人能用一个接口的例子通俗的解释一下?

  •  
  •   itechnology · 2022-02-16 11:06:25 +08:00 · 9355 次点击
    这是一个创建于 1019 天前的主题,其中的信息可能已经有所发展或是发生改变。
    阿里巴巴 JAVA 开发手册是这样定义的:

    DO ( Data Object ):与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
    DTO ( Data Transfer Object ):数据传输对象,Service 或 Manager 向外传输的对象。
    BO ( Business Object ):业务对象。 由 Service 层输出的封装业务逻辑的对象。
    AO ( Application Object ):应用对象。 在 Web 层与 Service 层之间抽象的复用对象模型,极为贴近展示层,复用度不高。
    VO ( View Object ):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
    POJO ( Plain Ordinary Java Object ):在本手册中,POJO 专指只有 setter/getter/toString 的简单类,包括 DO/DTO/BO/VO 等。

    但我感觉光看定义还是不容易理解,有没有人能用一个接口的来举个例子说一下
    53 条回复    2022-04-28 08:45:02 +08:00
    Oktfolio
        1
    Oktfolio  
       2022-02-16 11:21:58 +08:00   ❤️ 1
    DO selectByPrimayKey(Long id);

    DTO selectJoinedXxxx(Query quer);

    BO toBo(DO do);

    void addSomeBizData(BO bo);

    void doSomething(BO bo);

    interface api {
    DTO getById(Long id);
    }

    @Get("")
    VO getXxxxxVo(Long id);

    @Post("")
    void create(CreateXxxDTO dto);

    我是这么用的
    leeyuzhe
        2
    leeyuzhe  
       2022-02-16 11:45:34 +08:00
    @Oktfolio 但这些数据结构互相转不是造就了很多无用代码,如果两种结构区别不大的话
    welong
        3
    welong  
       2022-02-16 11:46:02 +08:00
    DTO VO BO 这几个用到的比较多吧。
    timethinker
        4
    timethinker  
       2022-02-16 11:47:13 +08:00   ❤️ 29
    画了一张图,凑合看吧

    notwaste
        5
    notwaste  
       2022-02-16 11:51:02 +08:00
    感觉没必要规定死,每个地方有每个地方不同的定义,目的都是统一规范罢了,个人认为只需要了解分层就可以,比如跟数据库交互的对象是一层称为 DTO ,controller 跟前端返回的对象是一层叫 VO (我们公司定义叫 Result )
    NotFoundEgg
        6
    NotFoundEgg  
       2022-02-16 13:08:15 +08:00
    我平时的习惯是
    controller 接收参数的实体类命名为 DTO 、返回的实体类命名为 VO
    在 controller-service 、service-service 中传递的实体类命名为 DTO
    DAO 的返回命名为 Entity
    javapythongo
        7
    javapythongo  
       2022-02-16 13:33:30 +08:00   ❤️ 3
    遇事不决 dto
    lower
        8
    lower  
       2022-02-16 13:40:53 +08:00
    我是一个 Entity 走天下,,实在不行用万能 Map 上
    lululau
        9
    lululau  
       2022-02-16 13:47:38 +08:00
    有用 Kotlin 写 Web 的吗,我想知道 Kotlin 里也这么多欧吗
    me221
        10
    me221  
       2022-02-16 14:10:12 +08:00
    这么多 o 太晕了 我只用了 entity vo dto
    lopssh
        11
    lopssh  
       2022-02-16 14:11:59 +08:00
    @qwe520liao 用什么工具画出来的呀?
    wolfie
        12
    wolfie  
       2022-02-16 14:14:25 +08:00   ❤️ 1
    DTO 接参
    DO 略
    VO 渲染
    BO 跟入参、响应 无关的,临时处理用的。
    echo1937
        13
    echo1937  
       2022-02-16 14:14:59 +08:00
    @lower #8 遇到万能 Map 最头疼了,不跑一次很难知道里面都有啥,魔术袋。
    q474818917
        14
    q474818917  
       2022-02-16 14:15:35 +08:00
    以一位从业多年经验告诉你,远离 java (这个最内卷的语言,没有之一)
    itechnology
        15
    itechnology  
    OP
       2022-02-16 14:24:22 +08:00
    @wolfie 感谢解释,简单明了
    timethinker
        16
    timethinker  
       2022-02-16 14:27:16 +08:00
    Stevenv
        17
    Stevenv  
       2022-02-16 14:40:19 +08:00
    原来不是我一个人。,。。。。
    chrosing
        18
    chrosing  
       2022-02-16 14:42:48 +08:00
    映射数据库用 entity 入参用 vo 出参用 dto
    xiangyuecn
        19
    xiangyuecn  
       2022-02-16 14:50:39 +08:00
    Map 一把梭😂
    Leviathann
        20
    Leviathann  
       2022-02-16 15:04:14 +08:00
    感觉有些时因为当时没有 graphql
    有些是为了类型安全
    但是由于是名义类型,所以必须声明一个 object 出来
    像 ts 是结构类型,只要字段一样就可以,返回一个 object literal 也能匹配上
    BeautifulSoap
        21
    BeautifulSoap  
       2022-02-16 15:04:25 +08:00
    所有对象中所,核心是 Business Object(或者理解成 DDD 中的 Entity 也行),写代码或者建模也应该是以 Business Object/Entity 为核心创建,其他都是围绕着 Entity 的。比如你想要持久化保存 Entity ,那么你自然就需要 Data Object ,因为同一个 Entity 保存在不同数据库甚至是调用微服务保存的时候,存储用的结构是会非常不一样的

    然后你想要把 Entity 的内容从 API 返回给调用方、或者吧 API 的请求参数复原成 Entity 的话,你也需要个对象来存放这种数据,那就是 DTO
    qingshuang
        22
    qingshuang  
       2022-02-16 15:21:18 +08:00
    我一直以为 DO 是 Domain Object 。。。
    qingshuang
        23
    qingshuang  
       2022-02-16 15:22:14 +08:00
    DO 我们这里一般都叫 PO
    chocotan
        24
    chocotan  
       2022-02-16 15:26:35 +08:00
    Entity 一把梭
    djFFFFF
        25
    djFFFFF  
       2022-02-16 15:37:34 +08:00
    @chocotan 感觉一把梭的话叫 DTO 比较好,Entity 通常用来表示数据库对象,就是 4 楼的 DO
    stephCurry
        26
    stephCurry  
       2022-02-16 16:01:17 +08:00   ❤️ 1
    甚至可以创造一个 RO Request Object...
    Jooooooooo
        27
    Jooooooooo  
       2022-02-16 17:59:26 +08:00
    通通 vo 一把梭
    flyfanc
        28
    flyfanc  
       2022-02-16 18:05:24 +08:00
    太复杂了,只用 entity ,其它情况 map
    sagaxu
        29
    sagaxu  
       2022-02-16 18:05:49 +08:00 via Android   ❤️ 5
    等你把 5 个 O 的 class 写好的时候,PHP 用万能 array 堆起的小屎山已经提测
    flighter
        30
    flighter  
       2022-02-16 18:07:38 +08:00
    DO 不是 Domain Object 么?
    awalkingman
        31
    awalkingman  
       2022-02-16 19:15:02 +08:00
    @lower 来人呐,把这个用 map 传参的拉出去枪毙十分钟
    orange
        32
    orange  
       2022-02-16 19:17:29 +08:00
    @sagaxu 形象 :)
    mritd
        33
    mritd  
       2022-02-16 20:05:20 +08:00 via iPhone
    歪楼

    潘森: 踩住 OOO 接 扎 接 碘盐 接 突突突
    fpure
        34
    fpure  
       2022-02-16 21:21:43 +08:00
    我写的代码里面一般只会存在简单的 model 、Query 、VO 三种对象
    Bingchunmoli
        35
    Bingchunmoli  
       2022-02-16 21:33:07 +08:00 via Android
    @leeyuzhe 学习的时候确实无用代码,但工作后各种需求,各种数据实体需要来回转换就有必要了
    yogogo
        36
    yogogo  
       2022-02-16 21:58:28 +08:00
    只用 entity dto
    数据库 entity
    接口 dto
    EvanLuo42
        37
    EvanLuo42  
       2022-02-16 23:22:54 +08:00 via iPhone
    @lululau ktor 吗,一般用个 dataclass 就好了吧
    Rocketer
        38
    Rocketer  
       2022-02-16 23:43:41 +08:00 via iPhone
    我个人的理解是:

    POJO 就是 Entity ,是数据对象的终极形态。

    但持久端可能使用不同的数据库,以后还有可能换库,所以 Entity 要转成数据库相关的 DO 才能存储。在某些情况下,Entity 和 DO 可能一模一样,但为了以后换库方便,仍然需要转一下。

    DTO 是 Service 向 Controller 输入输出数据用的,有时是处理过的,有时跟 Entity 一模一样。但为了命名统一,还是要转一下。

    其他 O 不知道是干啥用的,现在 Controller 返回的都是 JSON ,应该没有 VO 了吧?
    offswitch
        39
    offswitch  
       2022-02-17 09:10:19 +08:00
    @qingshuang Domain Object 这个是领域对象,是 DDD 里面的概念。
    NeoZephyr
        40
    NeoZephyr  
       2022-02-17 10:14:42 +08:00
    @lower Entity 指的是什么
    NeoZephyr
        41
    NeoZephyr  
       2022-02-17 10:15:38 +08:00
    @newskillsget 我们全部用的 map ,挺好的啊
    NeoZephyr
        42
    NeoZephyr  
       2022-02-17 10:15:59 +08:00
    @q474818917 你说哪个不内卷啊
    Asuka0947
        43
    Asuka0947  
       2022-02-17 10:24:27 +08:00
    只用 entity ,vo ,bo ;偷懒 entity 一把梭了,忽略部分字段。
    LowBi
        44
    LowBi  
       2022-02-17 11:00:03 +08:00 via Android
    偷懒了,太多了也太绕
    awalkingman
        45
    awalkingman  
       2022-02-17 12:37:59 +08:00
    @NeoZephyr 开发的时候时方便了,维护起来会要了老命(除非有及时更新的文档)
    MonkeyJon
        46
    MonkeyJon  
       2022-02-17 15:49:58 +08:00
    目前在用:
    VO:用于跟前端对接的出参(返回结果)
    DO:微服务之间的数据传输
    POJO:只跟数据库交互使用
    DTO:PO 满足不了的用 DTO 重写 PO 字段与数据库交互
    AO:我们是 Query,前端传的入参,仅存在于 Controller 层
    BO:我们命名为 Params ,query 转 params 才能进入 service 层
    itechnology
        47
    itechnology  
    OP
       2022-02-17 16:10:29 +08:00
    @MonkeyJon 感谢解释
    sknyyh
        48
    sknyyh  
       2022-02-18 10:38:42 +08:00
    @lower Map 维护的时候,真的是火葬场
    Uplay
        49
    Uplay  
       2022-02-20 19:54:35 +08:00
    @lululau 我们就用的 kotlin 感觉跟其他没什么区别
    wshcdr
        50
    wshcdr  
       2022-02-22 12:10:06 +08:00
    @qwe520liao AO 这里能举个例子不?
    timethinker
        51
    timethinker  
       2022-02-22 15:06:09 +08:00
    @wshcdr 简单的来说,你可以把 Controller 里面的一些逻辑转移到一个 Application Object/Service 上。

    分析一下原因,按理说每一个接口的逻辑应该是不同的,唯一的,但是不同接口之间可能也会复用到一些应用逻辑,如果这些逻辑在同一个 Controller 的不同的 Method 上( RequestMapping ),或许可以简单的创建一个私有的方法来搞定这些复用的逻辑。

    但是对于不同 Controller 需要复用的逻辑,又不适合放在普通的 Service 上,就可以创建一个 Application Object/Service 来封装了,此时的顺序变成了:

    Controller -> Application Object/Service -> (Domain)Service -> Repository/DAO 。

    另外再说一些题外话,大部分人应该没有这些顾虑或者思考,看不懂的略过即可:

    在 DDD 的战术模式中,领域服务( DomainService )一般只对单个聚合进行操作,且这些操作属于该领域自己的业务逻辑,只是不适合放到单个聚合上面,最重要的一点,聚合的任何操作都保证了不变性条件。

    但是某一个业务需求可能会跨聚合进行操作,又要保证事务一致,就可能会在上层再建立一个应用层,注意我这里说的应用层跟 DDD 中的应用服务( ApplicationService )不一样,它跨聚合操作这种行为本身就是因为模型分析得不到位。因此这种逻辑是不推荐的,因为它模糊了限界上下文之间的关系,但是从编码角度来说却是很方便的。

    想一想我有好几个 Service ,然后在 Controller 里面依次调用,只需要在 Controller 方法上加一个 @Transaction 的注解就可以保证事务一致,其中任何一个 Service 失败都将回滚数据,保证数据的一致性不被破坏。但其实这是一种偷懒的做法,或者说在是规模小的时候一种取巧省事的办法。
    NeoZephyr
        52
    NeoZephyr  
       2022-02-23 10:35:07 +08:00
    @newskillsget 也还好吧。每个人只关注自己往里面 put 的数据,别人 put 的都不动
    rehoni
        53
    rehoni  
       2022-04-28 08:45:02 +08:00
    为什么米有 Qo ,不过我基本只用 QO,DTO,VO,ENTITY
    QO:controller 接口接收的参数,POJO 类,用 oval 注解参数校验,至于直接用 QO 还是转换成 DTO 再给 service ,看心情...
    DTO:service 单表,联表查询返回的对象,POJO 类,继承 ENTITY ,用 excel 注解实现导出
    VO:特定约定返回给前端的结果用 VO ,从 DTO 做数据结构转换成 VO
    ENTITY:实体类对应数据库
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2487 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 04:42 · PVG 12:42 · LAX 20:42 · JFK 23:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.