Java 17 Records vs Lombok @Data: Which One Should You Use for DTOs?

Java 17 Records vs Lombok

For over a decade, Java developers had a love-hate relationship with boilerplate. To create a simple “data carrier” class, we had to write getters, setters, equals(), hashCode(), and toString() methods by hand.

Then came Lombok, the library that magically erased this boilerplate with a single @Data annotation. It was a lifesaver.

But with the release of Java 14 (standardized in Java 16/17), the JDK finally introduced a native solution: Records. Now, developers are asking: “Is Lombok dead? Should I migrate everything to Records?”

The answer is not a simple “Yes.” It depends entirely on whether you are building a DTO, a JPA Entity, or a Configuration Class.

⚡ TL;DR Summary:
  • For DTOs: Use Java Records. They are immutable, safer, and native to the JDK.
  • For JPA Entities: Use Lombok. Records cannot be Entities because they are immutable and lack a no-args constructor.
  • For Spring Config: Use Records with @ConfigurationProperties (New in Spring Boot 3).
  • The Shortcut: Don’t write either manually. Paste your JSON into our JSON to Java Converter to generate Records or Lombok classes instantly.

Round 1: The Case for Java 17 Records (The DTO King)

If your goal is to pass data from a Controller to a Service (or from an external API to your app), Records are the clear winner.

A Record in Java is explicitly designed to be a “transparent carrier for immutable data.”

Why Records Win for DTOs:

  • Immutability by Default: Once a Record is created, it cannot be changed. This eliminates bugs where data is accidentally modified as it passes through layers of your application.
  • Native Serialization: Jackson (the default JSON library in Spring Boot) supports Records out of the box. You don’t need extra annotations to map JSON to a Record.
  • Zero Dependencies: You don’t need to add a library or worry about IDE plugins breaking after an update.
// The Record Way (Java 17+) public record UserDto(String username, String email, int age) {}

Round 2: The Case for Lombok (The Entity King)

If Records are so great, why do we still need Lombok? The answer lies in Database Persistence (JPA/Hibernate).

JPA (Java Persistence API) has strict requirements that Records simply cannot meet:

  1. Entities must have a No-Args Constructor (Records do not).
  2. Entities must be Mutable (so Hibernate can update fields/IDs).
  3. Entities must not be Final (so Hibernate can create proxies for lazy loading).

Because Records are final and immutable, you cannot use a Record as a @Entity. It will crash your application at startup.

The “Lombok Trap” with Entities

While Lombok is necessary for Entities, using @Data on an Entity is a known anti-pattern. It generates toString() and hashCode() methods that include all fields, which can trigger infinite recursion loops with lazy-loaded relationships.

The Correct Lombok Pattern for Entities:

@Entity @Getter @Setter @ToString // Exclude lazy fields! @RequiredArgsConstructor public class User { // ... }

Round 3: Advanced Use Cases (Spring Boot 3 & Maps)

Beyond simple DTOs, Java Records have unlocked new patterns in modern development.

1. Type-Safe Configuration Properties

In Spring Boot 2, we often used Lombok’s @Data for configuration classes. In Spring Boot 3, the standard practice is now @ConfigurationProperties with Records.

@ConfigurationProperties(prefix = "app") public record AppConfig( @NotNull String name, @DefaultValue("1.0") String version ) {}

This guarantees that your application configuration is immutable once loaded—a massive safety improvement.

2. Map Keys & Caching

Have you ever tried to use a mutable object as a Key in a HashMap? It’s a disaster. If the object changes, the hash code changes, and you lose the value.

Records implement equals() and hashCode() based on all fields automatically and immutably. This makes them the perfect candidate for Map Keys or caching composite keys.

The Verdict: Decision Matrix

FeatureJava RecordLombok @Data
Best ForDTOs, Config, Map KeysJPA Entities
ImmutabilityEnforced (Final)Optional (Mutable default)
InheritanceNot SupportedSupported
BoilerplateZeroLow (via Annotations)

Frequently Asked Questions (FAQ)

Can I use Lombok with Java Records?

Yes, but you rarely need to. You can use Lombok’s @Builder on a Record to get a fluent builder API, or @With to create modified copies. However, annotations like @Data, @Getter, or @ToString are redundant because Records already provide these.

Do Records support inheritance?

No. A Java Record cannot extend another class (because it implicitly extends java.lang.Record). However, a Record can implement Interfaces. If you need class inheritance, you must use a standard class (and Lombok).

Are Records faster than Lombok?

Slightly. Records don’t require annotation processing at compile time, which speeds up builds. At runtime, they are optimized by the JVM, but the performance difference in most business apps is negligible. The main benefit is semantic correctness, not raw speed.


🚀 Developer Productivity Hack

Stop debating and start coding. If you have a JSON response from an API, don’t write the Java class by hand.

Paste your JSON into our Online JSON to Java Converter.

It has a toggle to instantly switch between generating Java 17 Records OR Lombok Classes. It even handles nested objects automatically.

Scroll to Top