Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# DTO (Data Transfer Object)
DTO — это простой объект (POJO), который служит для переноса данных между различными слоями приложения или между системами. Основная цель DTO — инкапсулировать данные и снизить количество вызовов, передавая необходимый набор данных за один раз.
Зачем нужен DTO?
- Decoupling — Entity класс не экспортируется наружу, скрыта внутренняя структура
- Selective exposure — передаются только нужные поля (скрываются sensitive данные)
- Network efficiency — передаём только необходимые данные по сети
- API stability — изменения в Entity не ломают API контракт
- Performance — избегаем lazy-loading проблем и N+1 queries
Пример: Entity vs DTO
// ENTITY — внутренняя модель данных
@Entity
@Table(name = "users")
public class User {
@Id
private Long id;
private String email;
private String password; // НЕ должен быть в DTO!
private String name;
@OneToMany
private List<Order> orders;
@ManyToOne
private Department department;
}
// DTO — то что видит клиент
public class UserDTO {
private Long id;
private String email;
private String name;
// password отсутствует!
}
// API Endpoint
@GetMapping("/users/{id}")
public UserDTO getUserById(@PathVariable Long id) {
User user = userService.findById(id);
return mapToDTO(user); // Entity -> DTO
}
Типы DTO
1. Request DTO (входные данные)
public class CreateUserRequest {
private String email;
private String name;
private String password;
// Валидация
@NotBlank
private String email;
@Size(min = 8, max = 50)
private String password;
}
2. Response DTO (исходящие данные)
public class UserResponse {
private Long id;
private String email;
private String name;
private LocalDateTime createdAt;
}
3. Nested DTO
public class OrderDTO {
private Long id;
private String orderNumber;
private UserDTO user; // вложенный DTO
private List<OrderItemDTO> items; // коллекция DTO
}
Маппинг Entity -> DTO
Вариант 1: Ручной маппинг
private UserDTO mapToDTO(User user) {
return new UserDTO(
user.getId(),
user.getEmail(),
user.getName()
);
}
Вариант 2: MapStruct (рекомендуется)
@Mapper(componentModel = "spring")
public interface UserMapper {
UserDTO toDTO(User user);
User toEntity(UserDTO dto);
List<UserDTO> toDTOs(List<User> users);
}
// Использование
@Service
public class UserService {
@Autowired
private UserMapper mapper;
public UserDTO getUser(Long id) {
User user = userRepository.findById(id).orElse(null);
return mapper.toDTO(user);
}
}
Вариант 3: Модель DTO с конструктором
public class UserDTO {
private Long id;
private String email;
private String name;
public UserDTO(User user) {
this.id = user.getId();
this.email = user.getEmail();
this.name = user.getName();
}
}
Best Practices
- Используй DTO для API — никогда не возвращай Entity прямо
- Избегай циклических зависимостей — не делай DTO.user.orders.user.orders
- Валидируй входные DTO — используй @Valid и Bean Validation
- Автоматизируй маппинг — MapStruct лучше ручного кода
- Имей отдельные Request/Response DTO — они могут отличаться
DTO с Lombok
@Data // @Getter @Setter @ToString @EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {
private Long id;
private String email;
private String name;
}