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
假设有三个实体类:Product、Category和 Stock,分别对应数据库中的 product、category和 stock表。
其中,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
假设有两个表:user 和 order,需要查询每个用户的所有订单。
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;
}
}