@Data
@Data is Lombok’s most powerful convenience annotation. A single @Data on a class generates a complete set of “data class” members at once, making it the go-to choice for DTOs and value objects. Because it bundles so much, it also has the most caveats — especially around JPA entities.
What @Data bundles
@Data is shorthand for applying five annotations together:
| Bundled annotation | What it generates |
|---|---|
@Getter | a getter for every field |
@Setter | a setter for every non-final field |
@ToString | a toString() over all fields |
@EqualsAndHashCode | equals() and hashCode() over all fields |
@RequiredArgsConstructor | a constructor for final and @NonNull fields |
So this concise class:
import lombok.Data;
@Data
public class CustomerDto {
private Long id;
private String name;
private String email;
}
is functionally equivalent to:
public class CustomerDto {
private Long id;
private String name;
private String email;
public CustomerDto() {} // no required fields → no-arg ctor
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
@Override public String toString() {
return "CustomerDto(id=" + id + ", name=" + name + ", email=" + email + ")";
}
@Override public boolean equals(Object o) { /* compares all fields */ }
@Override public int hashCode() { /* hashes all fields */ }
}
Note:
@Dataonly adds a@RequiredArgsConstructor. If every field is non-final and non-@NonNull, that constructor is a no-arg constructor. To also get an all-args constructor, add@AllArgsConstructorexplicitly.
When to use it
@Data shines on plain, mutable data carriers where you want the full accessor/identity/string suite:
- Request and response DTOs in your web layer.
- Configuration property holders bound from
application.yml. - Internal value objects that are compared by their contents.
@RestController
@RequestMapping("/api/customers")
public class CustomerController {
@PostMapping
public CustomerDto create(@RequestBody CustomerDto dto) {
// dto.getName(), dto.getEmail() all available via @Data
return dto;
}
}
For immutable DTOs, prefer Java records or pair @Getter with @Builder instead of @Data.
Cautions for JPA entities
Do not put @Data on JPA entities. The bundled @EqualsAndHashCode and @ToString operate over all fields, which causes real bugs in persistence:
// AVOID — @Data on an entity is dangerous
@Entity
@Data
public class Author {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "author")
private List<Book> books; // toString + equals will traverse this
}
Three concrete problems arise:
- Infinite recursion / lazy-loading blow-ups.
toString()walksbooks, eachBook.toString()walks back to itsAuthor, and so on. With bidirectional relationships this either loops forever or triggers unwanted lazy loads (andLazyInitializationExceptionoutside a session). - Broken equality.
equals()/hashCode()over a mutable, generatedidmean an entity’s hash changes after it is persisted, corruptingHashSet/HashMapmembership. - Unwanted setters.
@Datagenerates setters for the primary key and every field, undermining encapsulation of managed state.
The correct entity pattern uses focused annotations:
@Entity
@Getter
@Setter
@ToString(exclude = "books")
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Author {
@Id @GeneratedValue
@EqualsAndHashCode.Include
private Long id;
private String name;
@OneToMany(mappedBy = "author")
private List<Book> books;
}
The reasoning behind each choice is detailed in @EqualsAndHashCode & @ToString and Lombok Best Practices.
Warning: The single biggest Lombok mistake in Spring Boot projects is annotating an
@Entitywith@Data. Reserve@Datafor DTOs and value objects.