Skip to main content

1.DTO简介

DTO简介

DTO(Data Transfer Object)是一种用于在应用程序内部或不同系统之间传输数据的设计模式。它允许将数据从一个地方传输到另一个地方,同时隐藏了底层数据的细节,提高了代码的可维护性和可扩展性。

在Java中,DTO通常是一个简单的Java类,它包含了数据字段以及与之相关的一些方法。

常用场景

  • 传输数据 :在前后端交互或微服务之间传输数据时,DTO常常用于封装请求参数或响应结果。
  • 数据转换 :当数据从数据库查询或API调用中返回时,DTO可以用于将原始数据转换成更适合展示或处理的形式。
  • 解耦业务逻辑 :DTO可以将业务逻辑层的数据和视图层分离开来,降低了模块之间的耦合性。
  • API设计 :在设计API时,DTO可以定义API的输入和输出格式,提供了一种清晰的数据交互方式。

DTO的结构

DTO通常由一组数据字段和相关的访问方法组成,它们可以是JavaBean风格的普通类,也可以是更简单的数据传输对象。

public class UserDTO {
private Long id;
private String username;
private String email;

// Constructors
// Getters and setters
// Other methods
}

简单示例

假设有一个电子商务网站,需要展示商品信息给用户,同时还需要支持用户对商品进行下单操作。在这个场景中,我们可以使用DTO来传输商品信息。

DTO

public class ProductDTO {
private Long id;
private String name;
private String description;
private BigDecimal price;
private Integer stockQuantity;

// Constructors
// Getters and setters
// Other methods
}

服务类

@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;

public List<ProductDTO> getAllProducts() {
List<Product> products = productRepository.findAll();
return products.stream()
.map(this::convertToDTO)
.collect(Collectors.toList());
}

public ProductDTO getProductById(Long id) {
Product product = productRepository.findById(id).orElse(null);
if (product == null) {
throw new ProductNotFoundException("Product not found with id: " + id);
}
return convertToDTO(product);
}

private ProductDTO convertToDTO(Product product) {
ProductDTO productDTO = new ProductDTO();
productDTO.setId(product.getId());
productDTO.setName(product.getName());
productDTO.setDescription(product.getDescription());
productDTO.setPrice(product.getPrice());
productDTO.setStockQuantity(product.getStockQuantity());
return productDTO;
}
}

控制器类

@RestController
public class ProductController {
@Autowired
private ProductService productService;

@GetMapping("/products")
public ResponseEntity<List<ProductDTO>> getAllProducts() {
List<ProductDTO> productDTOs = productService.getAllProducts();
return ResponseEntity.ok(productDTOs);
}

@GetMapping("/products/{id}")
public ResponseEntity<ProductDTO> getProductById(@PathVariable Long id) {
ProductDTO productDTO = productService.getProductById(id);
return ResponseEntity.ok(productDTO);
}
}
  • ProductDTO用于传输商品信息给客户端。
  • ProductService中,通过 convertToDTO方法将 Product对象转换为 ProductDTO对象,以便在控制器中将其返回给客户端。
  • 控制器中的 ProductController负责处理HTTP请求,并调用相应的服务方法来获取商品信息并返回给客户端。

多表联查中DTO应用

在生产环境中,DTO在多表联查中的应用是非常常见的。例如,在一个电子商务网站中,可能需要同时获取商品信息以及与商品相关的其他信息,比如商品分类信息、库存信息等。在这种情况下,可以使用DTO来封装多表联查的结果,以便在业务逻辑层和展示层中使用。

示例1

假设有三个实体类:ProductCategoryStock,分别对应数据库中的 productcategorystock表。

其中,product表和 category表通过外键 category_id建立了关联,product表和 stock表通过外键 product_id建立了关联。

DTO类

public class ProductDetailDTO {
private Long id;
private String name;
private String description;
private BigDecimal price;
private String categoryName;
private Integer stockQuantity;

// Constructors
// Getters and setters
// Other methods
}

服务类

@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;

public List<ProductDetailDTO> getAllProductsWithDetails() {
List<Product> products = productRepository.findAll();
return products.stream()
.map(this::convertToDTO)
.collect(Collectors.toList());
}

public ProductDetailDTO getProductDetailById(Long id) {
Product product = productRepository.findById(id).orElse(null);
if (product == null) {
throw new ProductNotFoundException("Product not found with id: " + id);
}
return convertToDTO(product);
}

private ProductDetailDTO convertToDTO(Product product) {
ProductDetailDTO productDetailDTO = new ProductDetailDTO();
productDetailDTO.setId(product.getId());
productDetailDTO.setName(product.getName());
productDetailDTO.setDescription(product.getDescription());
productDetailDTO.setPrice(product.getPrice());
productDetailDTO.setCategoryName(product.getCategory().getName());
productDetailDTO.setStockQuantity(product.getStock().getQuantity());
return productDetailDTO;
}
}

控制器类

@RestController
public class ProductController {
@Autowired
private ProductService productService;

@GetMapping("/products")
public ResponseEntity<List<ProductDetailDTO>> getAllProductsWithDetails() {
List<ProductDetailDTO> productDTOs = productService.getAllProductsWithDetails();
return ResponseEntity.ok(productDTOs);
}

@GetMapping("/products/{id}")
public ResponseEntity<ProductDetailDTO> getProductDetailById(@PathVariable Long id) {
ProductDetailDTO productDetailDTO = productService.getProductDetailById(id);
return ResponseEntity.ok(productDetailDTO);
}
}
  • ProductDetailDTO用于传输多表联查的结果给客户端。
  • ProductService中,通过 convertToDTO方法将 Product对象转换为 ProductDetailDTO对象,同时获取与商品相关的其他信息,如商品分类名称和库存数量。
  • 控制器中的 ProductController负责处理HTTP请求,并调用相应的服务方法来获取商品详情信息并返回给客户端。

示例2

假设有两个表:userorder,需要查询每个用户的所有订单。

DTO 类

public class UserOrderDTO {

private Long userId;

private String username;

private List<Order> orders;

// ...
}

DAO 层

public interface UserMapper {

List<UserOrderDTO> listUserOrders();

}

public class UserServiceImpl implements UserService {

@Autowired
private UserMapper userMapper;

@Override
public List<UserOrderDTO> listUserOrders() {
return userMapper.listUserOrders();
}

}

Service 层

public class UserOrderDTO {

private Long userId;

private String username;

private List<Order> orders;

// ...
}

public class UserServiceImpl implements UserService {

@Autowired
private UserMapper userMapper;

@Override
public List<UserOrderDTO> listUserOrders() {
List<UserOrderDTO> dtos = userMapper.listUserOrders();
for (UserOrderDTO dto : dtos) {
// 将 Order 对象转换为前端需要的数据格式
// ...
}
return dtos;
}

}