@Entity, @Table, @Id
Beginner@Entity marks a class as a JPA-managed entity; @Table customises the table name and schema; @Id designates the primary key field; every entity must have exactly one @Id.
Overview
@Entity registers a Java class as a JPA-managed persistent object. Hibernate maps it to a database table. By default the table name matches the class name (case-insensitive). @Table customises the table name, schema, catalog, and adds unique constraints. @Id marks the primary key field — every entity must have exactly one. Composite primary keys use @IdClass or @EmbeddedId. Entities must have a no-arg constructor (public or protected) for Hibernate to instantiate them during load.
@Entity & @Table
@Entity is required on every persistent class. @Table is optional — use it when the table name differs from the class name, or when you need to define unique constraints or indexes at the JPA level.
// Basic entity — table name defaults to "Product" (case-insensitive)
@Entity
public class Product {
@Id
private Long id;
private String name;
}
// Custom table name, schema, and unique constraint
@Entity
@Table(
name = "tbl_products",
schema = "shop",
uniqueConstraints = {
@UniqueConstraint(name = "uq_product_sku", columnNames = {"sku"}),
@UniqueConstraint(name = "uq_product_barcode", columnNames = {"barcode_type", "barcode_value"})
},
indexes = {
@Index(name = "idx_product_category", columnList = "category_id"),
@Index(name = "idx_product_name", columnList = "name")
}
)
public class Product {
@Id
private Long id;
@Column(nullable = false, length = 50)
private String sku;
@Column(name = "barcode_type", length = 10)
private String barcodeType;
@Column(name = "barcode_value", length = 50)
private String barcodeValue;
// JPA requires a no-arg constructor (public or protected)
protected Product() {}
public Product(Long id, String sku) { this.id = id; this.sku = sku; }
}@Id and Composite Keys
@Id marks the primary key. For composite PKs, use @IdClass (two fields, separate class) or @EmbeddedId (single @Embeddable PK class). @IdClass is simpler for JPQL; @EmbeddedId is more type-safe.
// Single PK — most common
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
// Composite PK with @IdClass
public class OrderItemId implements Serializable {
private Long orderId;
private Long productId;
// equals + hashCode required
}
@Entity
@IdClass(OrderItemId.class)
@Table(name = "order_items")
public class OrderItem {
@Id
@Column(name = "order_id")
private Long orderId;
@Id
@Column(name = "product_id")
private Long productId;
private int quantity;
}
// Composite PK with @EmbeddedId (type-safe)
@Embeddable
public class OrderItemId implements Serializable {
private Long orderId;
private Long productId;
// equals + hashCode
}
@Entity
@Table(name = "order_items")
public class OrderItem {
@EmbeddedId
private OrderItemId id;
private int quantity;
}Entity Requirements & Best Practices
JPA imposes several requirements on entity classes. Following best practices ensures Hibernate works efficiently and avoids common pitfalls.
// JPA entity requirements:
// ✓ Must be annotated @Entity
// ✓ Must have a no-arg constructor (public or protected)
// ✓ Must have exactly one @Id field
// ✓ Must NOT be final (Hibernate needs to subclass for lazy proxies)
// ✓ Fields/methods must NOT be final either
// Best practices:
@Entity
@Table(name = "customers")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// ✓ Use field access (annotations on fields) — consistent access type
@Column(nullable = false, length = 254)
private String email;
// ✓ Implement equals/hashCode based on business key (NOT id)
// because id is null for transient entities
@NaturalId
private String email;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Customer c)) return false;
return email != null && email.equals(c.email);
}
@Override
public int hashCode() { return Objects.hashCode(email); }
}Key Points to Remember
- 1@Entity is required; @Table is optional — use it to customise table name or add constraints.
- 2Every entity must have exactly one @Id field and a no-arg constructor.
- 3Entities must not be final — Hibernate needs to subclass them for lazy proxying.
- 4@IdClass and @EmbeddedId support composite primary keys.
- 5Implement equals/hashCode based on a business key (natural ID), not the generated DB id.
- 6Define unique constraints and indexes via @Table annotations for JPA-managed schema generation.
Interview Questions
Sign in to ask AriaWhy must a JPA entity have a no-arg constructor?
Why should JPA entity classes not be declared final?
How do you map a composite primary key in JPA?
Why should you implement equals/hashCode on a business key rather than the generated ID?
What is the difference between @IdClass and @EmbeddedId for composite keys?
Ask Aria about @Entity, @Table, @Id
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.