Skip to content
Spring Boot sb lombok 3 min read

Lombok Best Practices

Lombok removes a huge amount of boilerplate, but used carelessly it hides surprising behavior and bites teams in JPA and serialization layers. This page distills the practical rules for using Lombok safely and consistently in a Spring Boot codebase.

When to use vs avoid

Lombok is most valuable on plain data carriers and on Spring beans where it expresses a clear, conventional pattern. It is risky on persistence entities and anywhere subtle generated behavior matters.

Use Lombok forBe careful / avoid on
DTOs and request/response modelsJPA @Entity classes (no @Data)
Configuration property holdersClasses with delicate equals/hashCode
Spring services (@RequiredArgsConstructor)Public API types you must keep stable
Value objects and buildersAnything where hidden methods confuse readers

Never put @Data on JPA entities

This is the single most important rule. @Data bundles @ToString and @EqualsAndHashCode over all fields, which on an entity causes infinite recursion across bidirectional relationships, surprise lazy loading (LazyInitializationException), and broken hash contracts when a generated id changes after persistence.

// DON'T
@Entity
@Data                       // recursion + broken equals
public class Author { /* ... */ }

// DO
@Entity
@Getter
@Setter
@ToString(exclude = "books")
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Author {
    @Id @GeneratedValue
    @EqualsAndHashCode.Include
    private Long id;
    @OneToMany(mappedBy = "author")
    private List<Book> books;
}

The full reasoning is in @EqualsAndHashCode & @ToString.

Prefer @RequiredArgsConstructor for injection

For Spring beans, declare dependencies as private final fields and use @RequiredArgsConstructor. This gives clean constructor injection, immutable dependencies, and trivial unit testing.

@Service
@RequiredArgsConstructor
public class OrderService {
    private final OrderRepository repository;
    private final PaymentClient paymentClient;
}

Avoid field injection (@Autowired on fields) entirely — it is harder to test and hides dependencies.

Do / Don’t quick reference

DoDon’t
Use @Data on DTOs and value objectsUse @Data on entities
Use @RequiredArgsConstructor for beansUse field-level @Autowired
Use @Builder.Default for default valuesAssume field initializers apply in builders
Use @EqualsAndHashCode.Include (allowlist)Compare entities on all mutable fields
Add @NoArgsConstructor when JPA/Jackson needs itForget the no-arg ctor after adding others
Pair @Getter + @Builder for immutable DTOsGenerate setters on immutable values
Pin the Lombok dependency as optional/providedShip Lombok as a runtime dependency

Use delombok to inspect or remove Lombok

delombok expands Lombok annotations into real Java source. It is useful for debugging “where did this method come from?”, for generating Javadoc, or for removing Lombok from a module entirely.

# Maven
mvn lombok:delombok

# Direct
java -jar lombok.jar delombok src/main/java -d target/delombok

This writes the fully expanded source so you can read exactly what the compiler sees.

Tip: When a generated method behaves unexpectedly, delombok the class and inspect the real code. It almost always reveals the issue (a missing @Builder.Default, an unintended setter, or an over-broad equals).

Team conventions

Consistency matters more than any single choice. A few conventions that scale well:

  • Centralize behavior with a lombok.config at the project root, for example to enforce a logging field name or copy annotations onto generated constructor parameters:
# lombok.config
config.stopBubbling = true
lombok.addLombokGeneratedAnnotation = true
lombok.equalsAndHashCode.callSuper = call
  • lombok.addLombokGeneratedAnnotation = true marks generated members with @lombok.Generated, so coverage tools like JaCoCo can exclude generated code from metrics.
  • Agree on one logger annotation (@Slf4j) across the codebase — see @Slf4j Logging.
  • Prefer Java records over @Value/@Data for immutable DTOs on Java 17+; reach for Lombok where records do not fit (mutable models, inheritance, builders on entities).
  • Document the entity equality strategy once and apply it everywhere.

Warning: Lombok modifies bytecode via annotation processing. If a build mysteriously cannot resolve generated methods, confirm annotation processing is enabled and that the IDE Lombok plugin matches the dependency version.

Last updated June 13, 2026
Was this helpful?