← Назад к вопросам

Что такое dto?

1.0 Junior🔥 151 комментариев
#REST API и микросервисы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# DTO (Data Transfer Object)

DTO — это простой объект (POJO), который служит для переноса данных между различными слоями приложения или между системами. Основная цель DTO — инкапсулировать данные и снизить количество вызовов, передавая необходимый набор данных за один раз.

Зачем нужен DTO?

  1. Decoupling — Entity класс не экспортируется наружу, скрыта внутренняя структура
  2. Selective exposure — передаются только нужные поля (скрываются sensitive данные)
  3. Network efficiency — передаём только необходимые данные по сети
  4. API stability — изменения в Entity не ломают API контракт
  5. 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

  1. Используй DTO для API — никогда не возвращай Entity прямо
  2. Избегай циклических зависимостей — не делай DTO.user.orders.user.orders
  3. Валидируй входные DTO — используй @Valid и Bean Validation
  4. Автоматизируй маппинг — MapStruct лучше ручного кода
  5. Имей отдельные Request/Response DTO — они могут отличаться

DTO с Lombok

@Data // @Getter @Setter @ToString @EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {
    private Long id;
    private String email;
    private String name;
}
Что такое dto? | PrepBro