JPA (Java Persistence API) annotations are metadata. These map Java classes to database tables and define how Java objects communicate with relational databases. Using these annotations we can manage database entities, relationships, and operations easily using object-relational mapping (ORM). These are available in the javax.persistence(old) or jakarta.persistence(latest) package. These are widely used in the Spring Boot applications.
This topic explains an overview of JPA annotations, their purposes, and examples of commonly used annotations.
Purpose of JPA Annotations
- These map Java classes and properties to database tables and columns.
- These make associations like One-to-One, One-to-Many, and Many-to-Many with tables using entity classes.
- These specify constraints, cascading rules, and fetching strategies.
- These enable developers to work with Java objects instead of writing raw SQL.
Common JPA Annotations
@Entity
It is used to mark a Java class as a database entity, mapping it to a database table.
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
@Entity
public class Product {
@Id
private Long id;
private String name;
private double price;
// Getters and Setters
}
@Table
It specifies the name of the table in the database. If not provided, the table name defaults to the class name created in the database.
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
@Entity
@Table(name = "products")
public class Product {
// Properties and Methods
}
@Id
It is used to make a property the primary key of the entity.
Example:
import jakarta.persistence.Id;
import jakarta.persistence.Entity;
@Entity
public class Product {
@Id
private Long id;
private String name;
// Getters and Setters
}
@GeneratedValue
It is used to generate automatically primary key value (e.g., auto-increment, sequence) in the database table.
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
//Other properties and methods
}
@Column
It is used to customise property mapping to a database column.
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.Column;
@Entity
public class Product {
@Column(name = "product_name", nullable = false, length = 100)
private String name;
// Other properties and methods
}
@Transient
It marks a property to be ignored by JPA (not persisted in the database).
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.Transient;
@Entity
public class Product {
private String name;
@Transient
private String tempData; // Will not be stored in the database
}
@Lob
It indicates a large object, such as CLOB or BLOB, for storing large text or binary data.
Example:
import jakarta.persistence.Lob;
public class Document {
@Lob
private byte[] fileData;
}
@Temporal
It is used for temporal type (DATE, TIME, or TIMESTAMP) of a date property of the entity.
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;
import java.util.Date;
@Entity
public class Event {
@Temporal(TemporalType.DATE)
private Date eventDate;
}
@Enumerated
It maps an enum type to a database column.
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.Enumerated;
import jakarta.persistence.EnumType;
@Entity
public class Product {
@Enumerated(EnumType.STRING)
private ProductCategory category;
}
Annotations for Relationships
@OneToOne
It defines a one-to-one relationship between entities.
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.OneToOne;
@Entity
public class User {
@OneToOne
private Profile profile;
}
@OneToMany
It is used to make a one-to-many relationship with entity.
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.OneToMany;
import java.util.List;
@Entity
public class Category {
@OneToMany(mappedBy = "category")
private List<Product> products;
}
@ManyToOne
It is used to make a many-to-one relationship with entity.
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
public class Product {
@ManyToOne
private Category category;
}
@ManyToMany
It defines a many-to-many relationship.
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToMany;
import java.util.List;
@Entity
public class Student {
@ManyToMany
private List<Course> courses;
}
Annotations for Fetching Strategies
@Fetch
It specifies fetching behavior for relationships (e.g., EAGER or LAZY).
Example:
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.OneToMany;
@Entity
public class Category {
@OneToMany(fetch = FetchType.LAZY)
private List<Product> products;
}
Best Practices for Using JPA Annotations
- Normalize Table and Column Names: Use @Table and @Column annotations to align with database naming conventions.
- Use @Transient Sparingly: Avoid persisting properties that are unnecessary for database storage.
- Choose Fetch Strategies Wisely: Use lazy fetching for performance and eager fetching for required data.
- Define Relationships Clearly: Specify @JoinColumn and mappedBy for bidirectional relationships to avoid confusion.
Conclusion
JPA annotations simplify database operations by enabling developers to work with Java objects instead of raw SQL. From defining entities, customise columns and relationships to configuring database behaviour, these annotations provide a powerful and intuitive way to manage data in Spring Boot applications. By mastering JPA annotations, we can create efficient, maintainable, and scalable ORM solutions tailored to our application’s needs.