Mapping Annotations
Learn the core Hibernate mapping annotations — @Entity, @Table, @Column, and @Id — and exactly what each one controls.
Introduction
The previous lesson used a bare-bones entity with mostly default behavior. In practice, you will frequently want more control — a different table name, a different column name, length constraints, or nullability rules. This lesson covers the four annotations that give you that control: @Entity, @Table, @Column, and @Id.
- What @Entity actually configures, beyond just marking a class.
- How @Table overrides the default table name and adds constraints.
- How @Column controls column name, length, nullability, and uniqueness.
- What @Id requires and how it is typically paired with other annotations.
@Entity
@Entity marks a class as a JPA-managed entity. By default, Hibernate uses the class's simple name as the table name — but @Entity also accepts an optional name attribute, used to reference the entity in queries (this is different from the table name, which @Table controls).
@Entity(name = "StudentEntity")public class Student { // ...}The name attribute on @Entity affects how the entity is referred to in JPQL/HQL queries (e.g., "FROM StudentEntity"), not the actual database table name — that is a common point of confusion.
@Table
@Table lets you explicitly set the database table name — useful when it should differ from the class name, such as following a plural naming convention. It also supports schema, catalog, and unique constraints.
import jakarta.persistence.Entity;import jakarta.persistence.Table;import jakarta.persistence.UniqueConstraint;
@Entity@Table(name = "students", uniqueConstraints = { @UniqueConstraint(columnNames = "email")})public class Student { // ...}Click Run to see what this code prints.
Without @Table, Hibernate would have used "Student" as the table name instead of "students."
@Column
@Column gives you control over an individual field's column: its name, whether it can be null, its maximum length, and whether it must be unique.
import jakarta.persistence.Column;
@Column(name = "full_name", nullable = false, length = 100)private String name;
@Column(unique = true, nullable = false)private String email;| Attribute | Purpose |
|---|---|
| name | Overrides the column name (defaults to the field name). |
| nullable | Whether the column allows NULL values (defaults to true). |
| length | Maximum length for String columns (defaults to 255). |
| unique | Adds a unique constraint on the column. |
Click Run to see what this code prints.
@Id
@Id marks exactly one field as the entity's primary key. Every entity must have one, and Hibernate uses it to uniquely identify each row and to detect whether an entity is new or already persisted.
import jakarta.persistence.Id;
@Idprivate Long id;On its own, @Id means the value must be assigned manually before saving, as in the previous lesson. Pairing it with @GeneratedValue lets the database or Hibernate generate the value automatically — covered in full in the next lesson.
A Fully Annotated Example
Putting all four annotations together produces a clear, explicit mapping.
import jakarta.persistence.*;
@Entity@Table(name = "students")public class Student {
@Id private Long id;
@Column(name = "full_name", nullable = false, length = 100) private String name;
@Column(unique = true, nullable = false) private String email;
public Student() { }
// getters and setters omitted for brevity}Click Run to see what this code prints.
Common Mistakes
- Confusing @Entity(name = ...) with @Table(name = ...) — they control different things (query name vs. table name).
- Assuming @Column is required on every field — it is optional and only needed when overriding defaults.
- Forgetting nullable = false on fields that should be mandatory, allowing invalid NULL data through.
- Placing @Id on a field type that cannot uniquely and reliably identify a row.
Best Practices
- Be explicit with @Table and @Column when the defaults do not match your team's naming conventions.
- Set nullable = false on any field that represents required data, matching your business rules.
- Use unique = true for fields like email that must not repeat, rather than enforcing it only in application code.
- Keep column length limits realistic and intentional rather than always relying on the 255-character default.
Frequently Asked Questions
No. If omitted, Hibernate simply uses the entity's class name as the table name.
No. Fields without @Column still get mapped, using the field name as the column name and sensible defaults.
Not directly with a single @Id each — composite primary keys use different annotations (@EmbeddedId or @IdClass), which are outside the scope of this lesson.
Common choices are Long, Integer, String, or UUID — any type that can reliably and uniquely identify a row.
Key Takeaways
- @Entity marks a class as JPA-managed; its name attribute affects queries, not the table name.
- @Table controls the actual database table name and table-level constraints.
- @Column controls a field's column name, nullability, length, and uniqueness.
- @Id marks the primary key field and is required on every entity.
Summary
With @Entity, @Table, @Column, and @Id, you now have precise control over how your Java classes map to database tables. Next, you will focus specifically on primary keys — how @GeneratedValue works, and the differences between IDENTITY, SEQUENCE, and AUTO generation strategies.