Curso de Spring Boot
En aplicaciones profesionales no es buena práctica devolver directamente las entidades de la base de datos.
En su lugar se usan DTOs.
DTO significa:
Data Transfer Object
Son objetos diseñados específicamente para enviar o recibir datos en la API.
10.1 Problema de devolver entidades directamente
Supongamos esta entidad:
1@Entity 2public class User { 3 4 @Id 5 @GeneratedValue 6 private Long id; 7 8 private String name; 9 10 private String email; 11 12 private String password; 13 14}
Si devolvemos esto directamente:
1@GetMapping("/users") 2public List<User> getUsers() { 3 return repository.findAll(); 4}
La respuesta sería:
1[ 2 { 3 "id": 1, 4 "name": "Ana", 5 "email": "ana@email.com", 6 "password": "123456" 7 } 8]
⚠️ Problema: estamos enviando la contraseña.
Esto es muy peligroso.
10.2 Qué es un DTO
Un DTO es una clase que contiene solo los datos que queremos exponer.
Ejemplo
1public class UserDTO { 2 3 private Long id; 4 5 private String name; 6 7 private String email; 8 9}
Ahora no existe el campo password.
10.3 Usar DTO en el Controller
1@GetMapping("/users") 2public List<UserDTO> getUsers() { 3 4 List<User> users = repository.findAll(); 5 6 return users.stream() 7 .map(user -> new UserDTO( 8 user.getId(), 9 user.getName(), 10 user.getEmail() 11 )) 12 .toList(); 13}
Resultado
1[ 2 { 3 "id": 1, 4 "name": "Ana", 5 "email": "ana@email.com" 6 } 7]
La contraseña ya no aparece.
10.4 DTO para crear usuarios
También podemos usar DTOs para recibir datos.
Ejemplo
1public class CreateUserDTO { 2 3 private String name; 4 5 private String email; 6 7 private String password; 8 9}
Controller
1@PostMapping("/users") 2public User createUser(@RequestBody CreateUserDTO dto) { 3 4 User user = new User(); 5 6 user.setName(dto.getName()); 7 user.setEmail(dto.getEmail()); 8 user.setPassword(dto.getPassword()); 9 10 return repository.save(user); 11 12}
10.5 Tipos de DTO comunes
En proyectos grandes suele haber varios DTO.
Ejemplo
1UserDTO 2CreateUserDTO 3UpdateUserDTO 4UserResponseDTO
Ejemplo
1public class UpdateUserDTO { 2 3 private String name; 4 5}
10.6 Problema del mapeo manual
Si tenemos muchas entidades, convertir manualmente puede ser pesado.
Ejemplo:
1UserDTO dto = new UserDTO( 2 user.getId(), 3 user.getName(), 4 user.getEmail() 5);
Si hay muchas entidades esto se vuelve repetitivo.
10.7 Usar MapStruct
Para solucionar esto se usa MapStruct.
MapStruct genera automáticamente el código de conversión.
10.8 Añadir dependencia MapStruct
En pom.xml:
1<dependency> 2 <groupId>org.mapstruct</groupId> 3 <artifactId>mapstruct</artifactId> 4 <version>1.5.5.Final</version> 5</dependency>
10.9 Crear un mapper
1@Mapper(componentModel = "spring") 2public interface UserMapper { 3 4 UserDTO toDTO(User user); 5 6 User toEntity(CreateUserDTO dto); 7 8}
Spring generará automáticamente el código.
10.10 Usar el mapper
1@Service 2public class UserService { 3 4 private final UserRepository repository; 5 private final UserMapper mapper; 6 7 public UserService(UserRepository repository, UserMapper mapper) { 8 this.repository = repository; 9 this.mapper = mapper; 10 } 11 12 public List<UserDTO> getUsers() { 13 14 return repository.findAll() 15 .stream() 16 .map(mapper::toDTO) 17 .toList(); 18 19 } 20 21}
10.11 Ejemplo completo arquitectura
1Controller 2 ↓ 3Service 4 ↓ 5Repository 6 ↓ 7Entity
DTOs se usan entre:
1Controller ↔ Service
10.12 Flujo completo
Cliente envía JSON:
1{ 2 "name": "Ana", 3 "email": "ana@email.com", 4 "password": "123456" 5}
Flujo:
1JSON → CreateUserDTO → Entity → Database
Respuesta:
1Entity → UserDTO → JSON
10.13 Buenas prácticas con DTO
No devolver entidades
Siempre usar DTO.
Separar DTO de entrada y salida
Ejemplo:
1CreateUserDTO 2UserResponseDTO
Validar DTO
Ejemplo:
1public class CreateUserDTO { 2 3 @NotBlank 4 private String name; 5 6 @Email 7 private String email; 8 9}
Usar mappers
Evita escribir conversiones manualmente.
10.14 Ventajas de usar DTO
| ventaja | explicación |
|---|---|
| seguridad | no expones campos sensibles |
| flexibilidad | API independiente de DB |
| control | decides qué enviar |
| mejor diseño | arquitectura limpia |
- Loading...