Java
Lombok
Annotations
Entity
Constructors

Why to use AllArgsConstructor and NoArgsConstructor together over an Entity?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Using Lombok's @NoArgsConstructor and @AllArgsConstructor together on a JPA entity is usually about satisfying two very different needs. One constructor exists because the persistence framework requires it, while the other exists as a convenience for application code, tests, or object mapping.

Why JPA Needs a No-Args Constructor

JPA providers such as Hibernate instantiate entities reflectively when loading them from the database. For that reason, the JPA specification expects an entity to have a no-argument constructor that is at least protected.

With Lombok, that often looks like this:

java
1import jakarta.persistence.Entity;
2import jakarta.persistence.Id;
3import lombok.AccessLevel;
4import lombok.Getter;
5import lombok.NoArgsConstructor;
6
7@Entity
8@Getter
9@NoArgsConstructor(access = AccessLevel.PROTECTED)
10public class Product {
11    @Id
12    private Long id;
13    private String name;
14    private int quantity;
15}

Making it protected is a good default because it keeps the constructor available to JPA without advertising an empty construction path to every caller in the codebase.

Why an All-Args Constructor Feels Convenient

@AllArgsConstructor is attractive because it removes boilerplate and makes object creation short:

java
1import lombok.AllArgsConstructor;
2
3@Entity
4@Getter
5@NoArgsConstructor(access = AccessLevel.PROTECTED)
6@AllArgsConstructor
7public class Product {
8    @Id
9    private Long id;
10    private String name;
11    private int quantity;
12}

Now you can write:

java
Product product = new Product(1L, "Keyboard", 5);

That is handy in unit tests, fixtures, import code, and simple demos. So the pair of annotations solves two separate problems:

  • JPA gets the empty constructor it needs
  • developers get a shortcut for full object creation

Why the Combination Can Be Dangerous on Real Entities

Convenience is not the same as good domain modeling. A generated all-arguments constructor exposes every field as a raw entry point, including fields that maybe should not be set directly.

For example:

  • generated ids may be set accidentally
  • audit fields may be bypassed
  • invariants may be skipped
  • bidirectional associations may be left inconsistent

This code compiles fine, but it may represent an invalid entity:

java
Product broken = new Product(99L, "Keyboard", -10);

Lombok does not know your business rules. It only generates a constructor from fields.

A Safer Pattern for Many Entities

A common compromise is to keep the JPA-friendly no-args constructor, but write your own validated constructor or factory method instead of exposing @AllArgsConstructor.

java
1import jakarta.persistence.Entity;
2import jakarta.persistence.GeneratedValue;
3import jakarta.persistence.Id;
4import lombok.AccessLevel;
5import lombok.Getter;
6import lombok.NoArgsConstructor;
7
8@Entity
9@Getter
10@NoArgsConstructor(access = AccessLevel.PROTECTED)
11public class Product {
12    @Id
13    @GeneratedValue
14    private Long id;
15
16    private String name;
17    private int quantity;
18
19    public Product(String name, int quantity) {
20        if (quantity < 0) {
21            throw new IllegalArgumentException("quantity cannot be negative");
22        }
23        this.name = name;
24        this.quantity = quantity;
25    }
26}

This keeps Hibernate happy while still making object creation part of the entity design instead of an accidental side effect of Lombok.

When Using Both Can Still Be Fine

Using both annotations is reasonable when:

  • the entity is simple
  • the fields do not carry many invariants
  • the all-args constructor is mostly for tests or internal fixtures

It becomes less attractive when the entity has important business meaning or lifecycle rules. In those cases, a generated all-args constructor can become the easiest way to create invalid state.

Common Pitfalls

  • Making the no-args constructor public when it exists only for JPA.
  • Using @AllArgsConstructor on entities with generated ids, relationships, or invariants that should not be bypassed.
  • Treating an entity as a plain data carrier instead of a persistence-backed domain object.
  • Assuming Lombok-generated constructors are automatically good API design.
  • Forgetting that builders or DTO constructors are often safer places for convenience than the entity itself.

Summary

  • '@NoArgsConstructor is usually present because JPA needs a no-argument constructor.'
  • '@AllArgsConstructor is a convenience for full object creation.'
  • Using both together can be practical, but it should be a deliberate design choice, not a default reflex.
  • For many real entities, a protected no-args constructor plus an explicit validated constructor is safer.
  • Treat constructor choice as part of entity modeling, not just as a Lombok shortcut.

Course illustration
Course illustration

All Rights Reserved.