VO、DTO、DO、PO 详解 + 举例说明

在软件开发中,尤其是面向对象编程和分层架构中,常常使用不同的数据对象来区分不同层次和不同职责的数据传输和处理。以下是 VO、DTO、DO、PO 的详细解释和举例说明:

1. VO(Value Object,值对象)

定义:VO 是一种不变的对象,通常用于表示某个数据的抽象,在系统中用于传递只读数据,常用于展示层。

特点

  • 不可变性:一旦创建,值对象的状态不能改变。
  • 无唯一标识:VO 不需要有唯一标识。

举例
假设我们有一个电商系统,需要在前端展示商品的详细信息。

public class ProductVO {
    private String name;
    private String description;
    private BigDecimal price;
    private String category;

    // 构造函数、getters 等省略

    public ProductVO(String name, String description, BigDecimal price, String category) {
        this.name = name;
        this.description = description;
        this.price = price;
        this.category = category;
    }
}

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

定义:DTO 用于在不同层之间传输数据,通常用于服务层与控制层之间的数据传输。DTO 可以是可变的,通常包含 getter 和 setter 方法。

特点

  • 仅用于数据传输:不包含业务逻辑。
  • 可以包含部分业务逻辑以确保数据一致性。

举例
例如,在电商系统中,从客户端接收到创建订单的数据。

public class OrderDTO {
    private Long productId;
    private Integer quantity;
    private String customerName;
    private String shippingAddress;

    // 构造函数、getters 和 setters 省略

    public OrderDTO(Long productId, Integer quantity, String customerName, String shippingAddress) {
        this.productId = productId;
        this.quantity = quantity;
        this.customerName = customerName;
        this.shippingAddress = shippingAddress;
    }

    // Getters 和 Setters 省略
}

3. DO(Domain Object,领域对象)

定义:DO 代表领域模型中的对象,包含业务逻辑和规则,直接与数据库中的数据对应。它们在持久化层和业务层之间传递。

特点

  • 直接映射到数据库表。
  • 包含业务逻辑。

举例
在电商系统中,表示数据库中的订单记录。

public class OrderDO {
    private Long id;
    private Long productId;
    private Integer quantity;
    private String customerName;
    private String shippingAddress;
    private LocalDateTime orderDate;

    // 构造函数、getters 和 setters 省略

    public OrderDO(Long id, Long productId, Integer quantity, String customerName, String shippingAddress, LocalDateTime orderDate) {
        this.id = id;
        this.productId = productId;
        this.quantity = quantity;
        this.customerName = customerName;
        this.shippingAddress = shippingAddress;
        this.orderDate = orderDate;
    }

    // Getters 和 Setters 省略
}

4. PO(Persistent Object,持久对象)

定义:PO 通常是与数据库中的表结构一一对应的 Java 对象,用于持久化数据。通常使用 ORM 框架(如 Hibernate 或 MyBatis)进行映射。

特点

  • 映射到数据库表。
  • 包含持久化相关的注解。

举例
在电商系统中,表示数据库中的商品记录。

@Entity
@Table(name = "product")
public class ProductPO {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "description")
    private String description;

    @Column(name = "price")
    private BigDecimal price;

    @Column(name = "category")
    private String category;

    // 构造函数、getters 和 setters 省略

    public ProductPO(String name, String description, BigDecimal price, String category) {
        this.name = name;
        this.description = description;
        this.price = price;
        this.category = category;
    }

    // Getters 和 Setters 省略
}

5. 系统举例:

下面是一个使用 Spring Boot 和 MyBatis 构建的电商系统示例,包含商品和订单功能,展示了 VO、DTO、DO、PO 在三层架构中的具体应用。

项目结构

src/main/java
└── com/example/ecommerce
    ├── EcommerceApplication.java
    ├── controller
    │   ├── ProductController.java
    │   └── OrderController.java
    ├── service
    │   ├── ProductService.java
    │   └── OrderService.java
    ├── mapper
    │   ├── ProductMapper.java
    │   └── OrderMapper.java
    ├── domain
    │   ├── ProductDO.java
    │   └── OrderDO.java
    ├── po
    │   ├── ProductPO.java
    │   └── OrderPO.java
    ├── dto
    │   └── OrderDTO.java
    └── vo
        └── ProductVO.java

1. PO(Persistent Object)

映射数据库表,用于持久化数据。

// ProductPO.java
package com.example.ecommerce.po;

public class ProductPO {
    private Long id;
    private String name;
    private String description;
    private BigDecimal price;
    private String category;

    // Constructors, getters and setters
    public ProductPO() {}

    public ProductPO(String name, String description, BigDecimal price, String category) {
        this.name = name;
        this.description = description;
        this.price = price;
        this.category = category;
    }

    // Getters and Setters
}

// OrderPO.java
package com.example.ecommerce.po;

import java.time.LocalDateTime;

public class OrderPO {
    private Long id;
    private Long productId;
    private Integer quantity;
    private String customerName;
    private String shippingAddress;
    private LocalDateTime orderDate;

    // Constructors, getters and setters
    public OrderPO() {}

    public OrderPO(Long productId, Integer quantity, String customerName, String shippingAddress, LocalDateTime orderDate) {
        this.productId = productId;
        this.quantity = quantity;
        this.customerName = customerName;
        this.shippingAddress = shippingAddress;
        this.orderDate = orderDate;
    }

    // Getters and Setters
}

2. DO(Domain Object)

包含业务逻辑。

// OrderDO.java
package com.example.ecommerce.domain;

import java.math.BigDecimal;
import java.time.LocalDateTime;

public class OrderDO {
    private Long id;
    private Long productId;
    private Integer quantity;
    private String customerName;
    private String shippingAddress;
    private LocalDateTime orderDate;

    public OrderDO(Long id, Long productId, Integer quantity, String customerName, String shippingAddress, LocalDateTime orderDate) {
        this.id = id;
        this.productId = productId;
        this.quantity = quantity;
        this.customerName = customerName;
        this.shippingAddress = shippingAddress;
        this.orderDate = orderDate;
    }

    // Getters and Setters

    // Business logic methods
    public BigDecimal calculateTotalPrice(BigDecimal productPrice) {
        return productPrice.multiply(new BigDecimal(this.quantity));
    }
}

3. DTO(Data Transfer Object)

用于表示层和业务逻辑层之间的数据传输。

// OrderDTO.java
package com.example.ecommerce.dto;

public class OrderDTO {
    private Long productId;
    private Integer quantity;
    private String customerName;
    private String shippingAddress;

    public OrderDTO(Long productId, Integer quantity, String customerName, String shippingAddress) {
        this.productId = productId;
        this.quantity = quantity;
        this.customerName = customerName;
        this.shippingAddress = shippingAddress;
    }

    // Getters and Setters
}

4. VO(Value Object)

用于表示层展示数据。

// ProductVO.java
package com.example.ecommerce.vo;

import java.math.BigDecimal;

public class ProductVO {
    private Long id;
    private String name;
    private String description;
    private BigDecimal price;
    private String category;

    public ProductVO(Long id, String name, String description, BigDecimal price, String category) {
        this.id = id;
        this.name = name;
        this.description = description;
        this.price = price;
        this.category = category;
    }

    // Getters
}

5. Mapper(MyBatis Mapper)

// ProductMapper.java
package com.example.ecommerce.mapper;

import com.example.ecommerce.po.ProductPO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface ProductMapper {
    @Select("SELECT * FROM product WHERE id = #{id}")
    ProductPO findById(Long id);
}

// OrderMapper.java
package com.example.ecommerce.mapper;

import com.example.ecommerce.po.OrderPO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Insert;

@Mapper
public interface OrderMapper {
    @Insert("INSERT INTO orders (product_id, quantity, customer_name, shipping_address, order_date) " +
            "VALUES (#{productId}, #{quantity}, #{customerName}, #{shippingAddress}, #{orderDate})")
    void save(OrderPO orderPO);
}

6. Service(业务逻辑层)

// ProductService.java
package com.example.ecommerce.service;

import com.example.ecommerce.mapper.ProductMapper;
import com.example.ecommerce.vo.ProductVO;
import com.example.ecommerce.po.ProductPO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ProductService {

    @Autowired
    private ProductMapper productMapper;

    public ProductVO getProductById(Long id) {
        ProductPO productPO = productMapper.findById(id);
        return new ProductVO(productPO.getId(), productPO.getName(), productPO.getDescription(), productPO.getPrice(), productPO.getCategory());
    }
}

// OrderService.java
package com.example.ecommerce.service;

import com.example.ecommerce.mapper.OrderMapper;
import com.example.ecommerce.domain.OrderDO;
import com.example.ecommerce.dto.OrderDTO;
import com.example.ecommerce.po.OrderPO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    public void createOrder(OrderDTO orderDTO) {
        OrderDO orderDO = new OrderDO(null, orderDTO.getProductId(), orderDTO.getQuantity(), orderDTO.getCustomerName(), orderDTO.getShippingAddress(), LocalDateTime.now());
        OrderPO orderPO = new OrderPO(orderDO.getProductId(), orderDO.getQuantity(), orderDO.getCustomerName(), orderDO.getShippingAddress(), orderDO.getOrderDate());
        orderMapper.save(orderPO);
    }
}

7. Controller(表示层)

// ProductController.java
package com.example.ecommerce.controller;

import com.example.ecommerce.service.ProductService;
import com.example.ecommerce.vo.ProductVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/products")
public class ProductController {

    @Autowired
    private ProductService productService;

    @GetMapping("/{id}")
    public ResponseEntity<ProductVO> getProduct(@PathVariable Long id) {
        ProductVO productVO = productService.getProductById(id);
        return ResponseEntity.ok(productVO);
    }
}

// OrderController.java
package com.example.ecommerce.controller;

import com.example.ecommerce.dto.OrderDTO;
import com.example.ecommerce.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/orders")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @PostMapping
    public ResponseEntity<String> createOrder(@RequestBody OrderDTO orderDTO) {
        orderService.createOrder(orderDTO);
        return ResponseEntity.ok("Order created successfully");
    }
}

8. 主应用程序类

// EcommerceApplication.java
package com.example.ecommerce;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.mybatis.spring.annotation.MapperScan;

@SpringBootApplication
@MapperScan("com.example.ecommerce.mapper")
public class EcommerceApplication {
    public static void main(String[] args) {
        SpringApplication.run(EcommerceApplication.class, args);
    }
}

结论

这个示例展示了如何使用 Spring Boot 和 MyBatis 实现一个电商系统的三层架构,分别使用 VO、DTO、DO 和 PO 来管理不同层次的数据对象。

  • PO(持久对象) 在数据访问层(DAO 层)中与数据库表进行映射和持久化。
  • DO(领域对象) 在业务逻辑层(Service 层)中包含业务逻辑。
  • DTO(数据传输对象) 用于表示层(Controller 层)和业务逻辑层(Service 层)之间的数据传输。
  • VO(值对象) 在表示层(Controller 层)中用于展示数据。

这种分层和对象的使用方式提高了系统的可维护性和可扩展性,使代码更清晰,职责分明。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/632078.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

32位处理的寻址方式

32位处理器兼容16位处理器的寻址方式&#xff0c;可以运行传统的16位代码。但是由于32位的处理器都拥有32位的寄存器和算数逻辑部件&#xff0c;而且同内存芯片之间的数据通路至少是32位的&#xff0c;因此&#xff0c;所有需要从寄存器或者内存地址处取得操作数的指令都被扩充…

Python专题:八、为整数增加小数点

1、题目 虽说很多人讨厌小数点&#xff0c;但是有时候小数点是必不可少的一项&#xff0c;请你使用强制类型转换为输入的整数增加小数点&#xff0c;并输出改变类型后的变量类型。 2、代码 import sysa float(int(input())) print(f"(a:.lf)",type(a),sep"\…

RTMP低延迟推流

人总是需要压力才能进步, 最近有个项目, 需要我在RK3568上, 推流到公网, 最大程度的降低延迟. 废话不多说, 先直接看效果: 数据经过WiFi发送到Inenter的SRS服务器, 再通过网页拉流的. 因为是打金任务, 所以逼了自己一把, 把RTMP推流好好捋一遍. 先说说任务目标, 首先是MPP编码…

什么是检索增强生成(Retrieval Augmented Generation)?RAG 架构如何实现?

检索增强生成&#xff08;Retrieval Augmented Generation&#xff09;时代 在不断发展的生成人工智能世界中&#xff0c;检索增强生成 (RAG) 标志着一项重大进步&#xff0c;它将检索模型的准确性与生成模型的创造性相结合&#xff0c;达到了准确&创新的更高层级。 这种…

vue嵌套路由

一、嵌套 children配置 1.父类路由 mymusic 2.子类路由 musicson 1.创建MusicSon组件 <template><div><p>从前和后来</p><p>唯一</p><p>运气来的似有若无</p></div> </template><script>export defaul…

关于电源3(整流滤波电路)

整流滤波电路 框图 一共有四种整流电路 以下是自己参考别人的文章https://blog.csdn.net/zhuguanlin121/article/details/130653498?ops_request_misc%257B%2522request%255Fid%2522%253A%2522171582622316800215096518%2522%252C%2522scm%2522%253A%252220140713.130102334…

【全开源】云界旅游微信小程序(源码搭建/上线/运营/售后/维护更新)

开启您的云端旅行新体验 一、引言 在快节奏的现代生活中&#xff0c;旅行成为了人们放松身心、探索世界的重要方式。让您的旅行更加便捷、高效&#xff0c;打造了云界旅游小程序&#xff0c;带您领略云端旅行的无限魅力。 二、小程序功能概览 云界旅游小程序集成了丰富的旅游…

SIP-7041 20W SIP广播网络有源音箱 校园广播20W木质SIP音箱

SIP-7041 20W SIP广播网络有源音箱 校园广播20W木质SIP音箱 一、描述 SIP-7041 20W SIP广播网络有源音箱 支持标准SIP协议 SIP-7041是我司的一款壁挂式网络有源音箱&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;可达到…

二三维战场仿真系统

收费工具&#xff0c;白嫖党勿扰 收费金额1万元 1 概述 给某个公司做了一个战场仿真系统&#xff0c;该公司给了5W的辛苦费。现在把相关功能部分提取出来&#xff0c;给需要的同学。 2 功能说明 战场仿真系统&#xff0c;分为三个部分&#xff1a; 服务器&#xff0c;用来发…

澳鹏Appen入选大模型产业链基础层图谱及案例研究

近日&#xff0c;由亿欧、上海市人工智能行业协会&#xff08;SAIA&#xff09;主办的2024全球开发者大会“百模大战”商业发展讲坛成功举办。作为全球开发者大会的平行技术论坛之一&#xff0c;本场论坛聚焦大模型产业&#xff0c;分析大模型赛道的竞争格局&#xff0c;洞悉大…

visual studio snippet常用注释片段

Visual Studio 2022 添加自定义代码片段_vs2022 代码片段-CSDN博客 dclass.snippet: <?xml version"1.0" encoding"utf-8"?> <CodeSnippets xmlns"http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> …

Hello, GPT-4o!

2024年5月13日&#xff0c;OpenAI 在官网正式发布了最新的旗舰模型 GPT-4o 它是一个 多模态模型&#xff0c;可以实时推理音频、视频和文本。 * 发布会完整版视频回顾&#xff1a;https://www.youtube.com/watch?vDQacCB9tDaw GPT-4o&#xff08;“o”代表“omni”&#xff0c…

haddoop三大核心组件

hadoop三大核心组件分别是hdfs、mapreduce和yarn。 1、hdfs&#xff1a;即分布式文件系统&#xff0c;用于存储hadoop集群中的大量数据。具有高容错性&#xff0c;可跨多个数据节点存储数据&#xff0c;并提供高吞吐量的数据访问&#xff1b; 2、mapreduce&#xff1a;用于大…

Python代码:一、HelloWorld

1、题目&#xff1a; 将字符串 Hello World! 存储到变量str中&#xff0c;再使用print语句将其打印出来。 2、代码 import sys str Hello World ! print(str)3、在sublime运行的结果

IT行业的现状与未来发展趋势:重塑生活与工作的无限可能

随着科技的飞速发展&#xff0c;IT行业已经逐渐从幕后走到台前&#xff0c;成为推动全球经济和社会发展的核心动力。从云计算的普及、大数据的崛起&#xff0c;到人工智能的爆发&#xff0c;再到物联网、5G通信和区块链技术的日新月异&#xff0c;这些技术不仅正在深刻改变着我…

2024年抖店保证金交多少?保证金常见问题解答,一文解决你所有疑惑

大家好&#xff0c;我是电商花花 新手如果想要开抖音小店&#xff0c;有一个大坑是必须要避开的。 就是我们店铺开通之后&#xff0c;我们一定要交保证金&#xff0c;如果不交&#xff0c;那就是0元开店。 很多新手听别人说做抖音小店可以0元开店&#xff0c;不用缴纳保证金就…

案例 | 澳鹏自动驾驶标注方案入选虎嗅智库行业报告

随着自动驾驶技术发展及方案演进&#xff0c;市场对于数据标注的数量和质量的需求都呈现指数级增长。传统的手工标注已不能满足标注需求&#xff0c;自动标注伴随大模型的发展应运而生。 在这一背景下&#xff0c;虎嗅智库发布《自动驾驶数据标注技术落地洞察》&#xff0c;并…

Nginx part3 创建一个https的网站

目录 HTTPS 公钥和密钥 加密解密方式&#xff1a; https搭建步骤 强调一下 1、准备环境 2、配置文件 3、制作证书 4、进行设置 HTTPS 啥是https&#xff0c;根据百度&#xff1a;HTTPS &#xff08;全称&#xff1a;Hypertext Transfer Protocol Secure&#xff09;&a…

8B10B编码(高速收发器五)

1、8B10B解决的问题 8B10B编码是1983年IBM公司提出的传输编码标准&#xff0c;通常用于高速收发器中&#xff0c;常见的JESD204B、SATA等接口协议&#xff0c;使用查表就可以实现编码和解码。 在这些高速收发器的接收端需要通过CDR技术去恢复时钟与数据的相位关系&#xff0c;在…

10个必备功能跨境电商ERP开发全指南

跨境电商平台开发是当前电商行业的热门话题。随着全球贸易的不断发展&#xff0c;企业越来越关注并重视跨境电商ERP系统的开发和应用。在本文中&#xff0c;我们将深入探讨跨境电商ERP开发的必备功能&#xff0c;为您呈现全面的指南。 1. 跨境订单管理 跨境电商平台需要具备全…