Discover how a simple object can protect your app and save hours of debugging!
Why DTOs matter in Spring Boot - The Real Reasons
Start learning this pattern below
Jump into concepts and practice - no test required
Imagine building a web app where your backend sends full database objects directly to the frontend every time a user requests data.
These objects contain sensitive info, extra fields, and complex relationships.
You try to manually pick and send only what the user needs by writing lots of code everywhere.
Manually selecting and transforming data is slow and error-prone.
You risk exposing sensitive data accidentally.
Code becomes messy and hard to maintain as your app grows.
Changing one part breaks others because data is tightly coupled.
DTOs (Data Transfer Objects) act as simple containers that carry only the data needed between backend and frontend.
They separate internal database models from what the user sees.
This keeps data safe, code clean, and makes maintenance easier.
return userRepository.findById(id); // sends full user entityreturn new UserDTO(user.getName(), user.getEmail()); // sends only needed dataDTOs enable clear, safe, and efficient data exchange between backend and frontend, making apps scalable and secure.
In an online store, you only send product name and price to customers, not internal stock levels or supplier info, using DTOs.
Manual data handling risks exposing sensitive info and creates messy code.
DTOs cleanly separate internal data from what is shared externally.
This leads to safer, clearer, and easier-to-maintain applications.
Practice
Solution
Step 1: Understand the purpose of DTOs
DTOs are designed to carry only the necessary data between processes or layers, avoiding exposure of internal details.Step 2: Analyze the options
To carry only the data we want to share and hide internal details correctly states the purpose of DTOs. The other options describe incorrect or harmful uses.Final Answer:
To carry only the data we want to share and hide internal details -> Option DQuick Check:
DTOs protect and simplify data transfer = D [OK]
- Thinking DTOs replace entities fully
- Assuming DTOs increase data size
- Believing DTOs slow down the app
Solution
Step 1: Identify correct DTO structure
A DTO is a simple class with private fields and public getters/setters, without annotations like @Entity or @Repository.Step 2: Evaluate each option
public class UserDTO { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } correctly defines a DTO class with fields and accessors. @Entity public class UserDTO { private String name; private int age; } wrongly uses @Entity, which is for database entities. public interface UserDTO { String getName(); int getAge(); } defines an interface, not a DTO class. @Repository public class UserDTO { private String name; private int age; } wrongly uses @Repository, which is for data access layers.Final Answer:
public class UserDTO { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } -> Option AQuick Check:
DTO = simple class with getters/setters = B [OK]
- Adding @Entity annotation to DTO
- Using interfaces instead of classes for DTO
- Marking DTO as @Repository
/user?
@GetMapping("/user")
public UserDTO getUser() {
UserDTO dto = new UserDTO();
dto.setName("Alice");
dto.setAge(30);
return dto;
}Solution
Step 1: Understand default JSON serialization in Spring Boot
Spring Boot uses Jackson to convert returned objects to JSON, serializing all public getters by default.Step 2: Analyze the returned UserDTO object
UserDTO has name and age fields with getters, so JSON will include both as simple key-value pairs.Final Answer:
{"name":"Alice","age":30} -> Option CQuick Check:
DTO fields serialize as JSON keys = A [OK]
- Expecting nested JSON with class name
- Assuming partial fields serialize
- Thinking serialization causes error
public class ProductDTO {
private String name;
private int price;
public ProductDTO(String name, int price) {
this.name = name;
this.price = price;
}
}Solution
Step 1: Identify deserialization requirements
Jackson requires a default no-argument constructor to create an instance before setting fields via setters or reflection.Step 2: Check the DTO class
This class only has a parameterized constructor and no default constructor, causing Jackson to fail during deserialization.Final Answer:
Missing default no-argument constructor -> Option BQuick Check:
Jackson needs no-arg constructor = A [OK]
- Thinking fields must be public
- Adding @Autowired to constructor parameters
- Confusing DTO with entity needing @Entity
User with many fields, but you want to expose only id and email in your API response. How should you use a DTO to achieve this cleanly?Solution
Step 1: Understand data exposure risks
Returning the full User entity exposes all fields, risking sensitive data leaks.Step 2: Use DTO to control data
Creating a UserDTO with only id and email fields and mapping User to UserDTO ensures only desired data is sent.Step 3: Evaluate other options
Return the User entity directly and ignore unwanted fields in the frontend risks exposing all data. Add @JsonIgnore to all unwanted fields in the User entity mixes entity with serialization concerns and can be error-prone. Use the User entity but rename unwanted fields to empty strings is a bad practice and confusing.Final Answer:
Create a UserDTO with only id and email fields, map User to UserDTO before returning -> Option AQuick Check:
DTOs control exposed data = C [OK]
- Returning full entity directly
- Using @JsonIgnore on entity fields
- Modifying entity fields to hide data
