Spring Boot + JPA | Java Persistence API : A Practical Guide
When building database-driven applications with Spring Boot, Java Persistence API (JPA) simplifies data access by abstracting away the complexities of SQL and providing a seamless way to interact with relational databases. Spring Boot integrates JPA with minimal configuration, leveraging powerful tools like Hibernate for object-relational mapping (ORM). This practical guide covers JPA essentials, from entity mapping to custom queries, while showcasing how to implement pagination and sorting for better data management.
Table of Contents
- Entity Mapping Basics
- Repository Interfaces (CrudRepository, JpaRepository)
- Pagination and Sorting
- Custom Queries with @Query
- External Resources for Further Learning
- Final Thoughts
Entity Mapping Basics
What is Entity Mapping?
Entity mapping is the process of linking Java objects (entities) to relational database tables. This is foundational in JPA, allowing developers to manage database records as objects in their applications.
Entities are annotated with JPA-specific annotations, such as @Entity
, @Table
, @Id
, and @Column
, to define their relationship with database tables and columns.
Example
User.java
package com.example.demo.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Column;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false)
private String email;
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Explanation of Key Annotations
@Entity
Marks the class as a JPA entity, meaning it corresponds to a database table.@Id
Specifies the primary key field of the table.@GeneratedValue
Defines primary key generation strategy (e.g.,IDENTITY
for auto-increment).@Column
Customizes the column properties, such asnullable
,unique
, orlength
.
Table Creation
When you run the application, JPA (with Hibernate) will use the above entity to create the User
table in the connected database.
Generated SQL:
CREATE TABLE User (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
email VARCHAR(255) NOT NULL
);
Repository Interfaces (CrudRepository, JpaRepository)
Spring Boot provides repository interfaces to simplify database interactions. These repositories abstract data access layers and eliminate the need to write boilerplate code for common operations.
CrudRepository
The CrudRepository
interface provides basic CRUD (Create, Read, Update, Delete) functionality for your entities. It is a generic interface and works with any entity type.
Example Repository:
package com.example.demo.repository;
import com.example.demo.model.User;
import org.springframework.data.repository.CrudRepository;
public interface UserRepository extends CrudRepository<User, Long> {
}
Available methods include:
save(S entity)
: Saves or updates the entity.findById(ID id)
: Retrieves an entity by its ID.findAll()
: Returns all entities.deleteById(ID id)
: Deletes an entity by ID.
JpaRepository
The JpaRepository
interface extends CrudRepository
and provides additional functionality specific to JPA, such as pagination and sorting.
Example Repository:
package com.example.demo.repository;
import com.example.demo.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
}
Additional methods:
findAll(Pageable pageable)
: Supports pagination.findAll(Sort sort)
: Retrieves sorted data.- Built-in methods for advanced querying, like retrieving data based on conditions.
When to Use Which?
- Use
CrudRepository
for simple CRUD operations. - Use
JpaRepository
when you need pagination, sorting, or custom query methods.
Pagination and Sorting
Large datasets are often impractical to load all at once. Pagination and sorting help efficiently manage and retrieve data.
Pagination Example
The Pageable
interface is used to define page size, number, and sorting criteria.
Controller Method:
@GetMapping("/users")
public Page<User> getUsers(Pageable pageable) {
return userRepository.findAll(pageable);
}
Request Example:
GET http://localhost:8080/users?page=0&size=5
Response:
- Returns the first page of data with 5 users per page.
Sorting Example
To sort records, pass a Sort
parameter:
@GetMapping("/users/sort")
public List<User> getUsersSorted(Sort sort) {
return userRepository.findAll(sort);
}
Request Example:
GET http://localhost:8080/users/sort?sort=username,asc
Response:
- Users sorted alphabetically by their username.
You can also combine pagination and sorting like this:
Pageable pageable = PageRequest.of(0, 5, Sort.by("username").ascending());
Page<User> page = userRepository.findAll(pageable);
Custom Queries with @Query
Sometimes, you need more advanced or optimized queries that cannot be expressed using the built-in methods. For such cases, Spring Data provides the @Query
annotation to define custom JPQL (Java Persistence Query Language) or SQL queries.
Example Query
Retrieve users by username:
@Query("SELECT u FROM User u WHERE u.username = ?1")
Optional<User> findByUsername(String username);
Usage Example:
Optional<User> user = userRepository.findByUsername("john_doe");
Native SQL Queries
For complex requirements, you can also use native SQL:
@Query(value = "SELECT * FROM User WHERE email LIKE %?1%", nativeQuery = true)
List<User> findByEmailContaining(String keyword);
Parameters Example
You can use parameterized queries to avoid SQL injection:
@Query("SELECT u FROM User u WHERE u.email = :email")
Optional<User> findByEmail(@Param("email") String email);
External Resources for Further Learning
- Spring Data JPA Documentation
- Hibernate ORM Documentation
- Wikipedia on Object-Relational Mapping (ORM)
- Guide to Pagination in Spring Data JPA by Baeldung
Final Thoughts
Spring Boot and JPA simplify database-driven application development by providing robust abstractions for entity mapping, data repositories, and advanced querying. This guide has covered the foundational practices for effectively using Spring Boot with JPA, from defining entities to implementing custom queries.
By understanding how to leverage Spring Data repositories and JPA features like pagination, sorting, and mapping, you can develop efficient, maintainable, and scalable applications. Bookmark this guide as a reference for building JPA-powered applications in Spring Boot!