๐Ÿ”ด The Error You're Seeing

Confirm this matches your console output. If it does, you're in the right place.

ERROR LOGjava.lang.StackOverflowError: null at com.devinhyderabad.entity.User.hashCode(User.java:20) at java.base/java.util.AbstractList.hashCode(AbstractList.java:541) at com.devinhyderabad.entity.Order.hashCode(Order.java:25) at java.base/java.util.AbstractList.hashCode(AbstractList.java:541) at com.devinhyderabad.entity.User.hashCode(User.java:20) ... (repeats hundreds of times)

โšก Quick Fix Works 80% of the time

Stop using @Data on JPA Entities. Use @Getter and @Setter instead.

@Entity @Getter @Setter public class User { ... }

๐Ÿง  Why this Happens

Tap to expand the deep technical explanation

Lombok's @Data annotation automatically generates equals() and hashCode() methods that inspect every field. When two entities have a bidirectional relationship (User -> Orders -> User), calling user.hashCode() triggers order.hashCode(), which triggers user.hashCode() again, creating an infinite loop until the JVM stack overflows.

The HITEC City Parking Spot Analogy:

Imagine two mirrors facing each other. When you look into one mirror, you see an infinite tunnel of mirrors reflecting each other. Lombok's equals() tries to look all the way down the tunnel until it crashes.

๐Ÿ” How to Reproduce Confirm this is your error

Use Lombok @Data on JPA entities with a bidirectional relationship, then save or find them. hashCode() recurses forever between the two entities and throws StackOverflowError.

๐Ÿ› ๏ธ Solutions (3 Ways to Fix)

Solution 1โœ“ Most common cause

Replace @Data with @Getter and @Setter

๐Ÿ‘‰ Use this on all JPA @Entity classes.

@Data generates equals() and hashCode() that include all fields. If User has a List of Orders, and Order has a User, they call each other infinitely. @Getter/@Setter avoid generating equals/hashCode.

// BAD @Entity @Data public class User { @OneToMany private List<Order> orders; } // GOOD @Entity @Getter @Setter public class User { @OneToMany private List<Order> orders; }
Solution 2

Exclude the relationship field from equals/hashCode

๐Ÿ‘‰ Use this if you still want Lombok to generate equals/hashCode, but safely.

Use @EqualsAndHashCode(exclude = "orders") to tell Lombok to ignore the bidirectional field.

@Entity @Data @EqualsAndHashCode(exclude = "orders") public class User { @OneToMany private List<Order> orders; }
Solution 3

Implement equals/hashCode manually using ID

๐Ÿ‘‰ Use this as the enterprise best practice for JPA entities.

Do not use Lombok for entity equality. Write custom equals() and hashCode() methods that only compare the primary key (@Id).

@Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof User)) return false; return id != null && id.equals(((User) o).getId()); } @Override public int hashCode() { return getClass().hashCode(); }

๐Ÿ“‹ Version Notes

Spring Boot 2.x

Lombok interacts with Hibernate 5.

Spring Boot 3.x

Lombok interacts with Hibernate 6. Same risk of StackOverflow.

๐Ÿ›ก๏ธ How to Prevent This Next Time

Never use @Data on JPA @Entity classes. Always use @Getter and @Setter, and implement custom equals/hashCode based on the ID.

Course Search
Search across all chapters & stages
๐Ÿ“–

Search the course

Type any topic โ€” branching, stash, rebase, hooks โ€” and jump straight to that chapter.

merge branchesgit stashundo commitrebase