100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Java

Defining JPA Entities

Learn how to model database tables as Java classes using JPA annotations, covering identifiers, column mapping, and entity relationships.

Data LayerBeginner10 min readJul 10, 2026
Analogies

Anatomy of a JPA Entity

A JPA entity is a plain old Java object annotated with @Entity that Hibernate maps to a database table. At minimum it needs a no-argument constructor, a field annotated with @Id to identify the primary key, and getters/setters (or, increasingly, a record-friendly pattern for read-heavy DTOs, though mutable entities remain the norm). By default, the class name maps to a table of the same name and each field maps to a column of the same name, both of which can be overridden with @Table(name = "...") and @Column(name = "...").

🏏

Cricket analogy: An @Entity class is like a player's official ICC profile card — the class fields (name, id, battingAverage) map directly to the columns of that record, just as a player's stats map to fields tracked in the official database.

Identifiers and Generation Strategies

Every entity needs a primary key, marked with @Id, and typically paired with @GeneratedValue to let the database or Hibernate assign values automatically. GenerationType.IDENTITY delegates ID generation to the database's auto-increment column (common with MySQL and PostgreSQL's serial/identity columns), GenerationType.SEQUENCE uses a database sequence object and allows Hibernate to batch inserts more efficiently, and GenerationType.UUID (added in Hibernate 6 / Jakarta Persistence 3.1) generates a random UUID client-side, which is useful for distributed systems where IDs must be assignable before an insert.

🏏

Cricket analogy: GenerationType.IDENTITY is like a stadium assigning ticket numbers sequentially as fans pass through the turnstile, one at a time, whereas SEQUENCE is like the ticketing system pre-reserving a batch of numbers for a whole stand at once.

Mapping Fields and Constraints

Beyond the identifier, @Column lets you control the mapped column's name, nullability (nullable = false), length (length = 500 for a VARCHAR), and uniqueness (unique = true), while @Enumerated(EnumType.STRING) is the recommended way to persist Java enums as readable text rather than fragile ordinal integers. Validation annotations from Jakarta Bean Validation, like @NotNull, @Size, and @Email, are commonly layered on top of JPA mappings so that constraints are enforced both at the application layer (via @Valid on controller input) and, where mirrored with @Column(nullable = false), at the database layer too.

🏏

Cricket analogy: @Enumerated(EnumType.STRING) is like storing a dismissal type as 'LBW' or 'CAUGHT' in the scorecard instead of a cryptic numeric code 3 or 5 that only makes sense if you memorize the scoring manual.

java
@Entity
@Table(name = "books")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_seq")
    @SequenceGenerator(name = "book_seq", sequenceName = "book_seq", allocationSize = 50)
    private Long id;

    @Column(name = "title", nullable = false, length = 250)
    private String title;

    @Column(unique = true, length = 13)
    private String isbn;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private BookStatus status;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "author_id")
    private Author author;

    protected Book() {
        // required no-arg constructor for JPA
    }

    public Book(String title, String isbn, Author author) {
        this.title = title;
        this.isbn = isbn;
        this.author = author;
        this.status = BookStatus.DRAFT;
    }

    // getters and setters omitted for brevity
}

Modeling Relationships

JPA supports four relationship annotations — @OneToOne, @OneToMany, @ManyToOne, and @ManyToMany — each of which can be configured with a fetch strategy (FetchType.LAZY or FetchType.EAGER) and a cascade behavior (CascadeType.PERSIST, MERGE, REMOVE, etc.). The @ManyToOne side is almost always the owning side because it holds the foreign key column via @JoinColumn, while the inverse @OneToMany side uses mappedBy to point back at the owning field rather than creating a second, redundant foreign key or join table.

🏏

Cricket analogy: A @ManyToOne from Player to Team is like each player's scorecard entry pointing to a single team ID, while the team's @OneToMany squad list is just the inverse view assembled by querying which players point to that team.

Default to FetchType.LAZY for @ManyToOne and @OneToOne associations by explicitly setting fetch = FetchType.LAZY, since the JPA default for these is EAGER — the opposite of most collection associations. Eager loading on the wrong side is a common source of unexpected N+1 queries and oversized result sets.

Avoid @Data from Lombok on JPA entities that participate in bidirectional relationships — the generated equals/hashCode and toString can recurse infinitely across the association (Book references Author, Author's toString lists Books, which reference Author again) and trigger a StackOverflowError or accidentally load the entire object graph.

  • @Entity classes need a no-arg constructor and an @Id field; table/column names default to the class/field name but can be overridden.
  • @GeneratedValue supports IDENTITY, SEQUENCE, and UUID strategies, each with different performance and distributed-system trade-offs.
  • @Column controls nullability, length, and uniqueness; @Enumerated(EnumType.STRING) is preferred over ordinal enum storage.
  • The @ManyToOne side owns the foreign key via @JoinColumn; the @OneToMany side is the inverse, declared with mappedBy.
  • Default @ManyToOne/@OneToOne to FetchType.LAZY explicitly, since JPA's built-in default for those is EAGER.
  • Cascade types like PERSIST and REMOVE control whether operations on the parent propagate to associated child entities.
  • Avoid Lombok's @Data on entities with bidirectional associations to prevent recursive equals/hashCode/toString bugs.

Practice what you learned

Was this page helpful?

Topics covered

#Java#SpringBootStudyNotes#WebDevelopment#DefiningJPAEntities#Defining#JPA#Entities#Anatomy#StudyNotes#SkillVeris