JPA (Java Persistence API) is a Java specification used to manage relational data in Java applications.
It provides a standard way to map Java objects to database tables.
Spring Boot uses Hibernate as the default JPA implementation.
Java Object ↔ JPA/Hibernate ↔ Database Table
| Java Class | Database Table |
|---|---|
| User.java | user |
| Product.java | product |
| Order.java | orders |
Without JPA (JDBC):
With JPA:
ORM maps Java objects to database tables.
| Java | Database |
|---|---|
| Class | Table |
| Object | Row |
| Field | Column |
@Entity
public class Student {
@Id
private Long id;
private String name;
}
Application
|
Spring Data JPA
|
JPA Specification
|
Hibernate (Implementation)
|
JDBC
|
Database
| Layer | Responsibility |
|---|---|
| Application | Business Logic |
| Spring Data JPA | Repository abstraction |
| JPA | Specification |
| Hibernate | ORM implementation |
| JDBC | Database connectivity |
| Annotation | Purpose |
|---|---|
| @Entity | Marks class as database table |
| @Table | Custom table name |
| @Id | Primary key |
| @GeneratedValue | Auto ID generation |
| @Column | Customize column |
| @Transient | Ignore field |
| @Temporal | Date mapping |
import jakarta.persistence.*;
@Entity
@Table(name = "students")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="student_name")
private String name;
private String email;
}
public interface StudentRepository
extends JpaRepository<Student, Long> {
}
Automatically provides:
studentRepository.save(student);
Student student = studentRepository.findById(1L).orElse(null);
List<Student> students = studentRepository.findAll();
studentRepository.deleteById(1L);
public interface StudentRepository
extends JpaRepository<Student, Long> {
List<Student> findByName(String name);
List<Student> findByEmail(String email);
List<Student> findByNameAndEmail(String name, String email);
}
SELECT * FROM students WHERE name = ?
@Query("SELECT s FROM Student s WHERE s.name = :name")
List<Student> getStudentsByName(String name);
@Query(value="SELECT * FROM students WHERE name = :name",
nativeQuery = true)
List<Student> getStudentsNative(String name);
| Relationship | Description |
|---|---|
| OneToOne | One record linked to one |
| OneToMany | One record → many |
| ManyToOne | Many → one |
| ManyToMany | Many ↔ many |
Student | | 1 | |------ * Courses
@Entity
public class Student {
@Id
private Long id;
@OneToMany(mappedBy = "student")
private List<Course> courses;
}
@Entity
public class Course {
@Id
private Long id;
@ManyToOne
private Student student;
}
spring.datasource.url=jdbc:mysql://localhost:3306/springdb spring.datasource.username=root spring.datasource.password=root spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true
New (Transient)
|
v
Managed (Persistent)
|
v
Detached
|
v
Removed
Controller
|
Service Layer
|
Repository Layer (JPA)
|
Hibernate
|
Database
UserController
|
UserService
|
UserRepository (JpaRepository)
|
MySQL
@Transactional
public void saveStudent(Student student){
studentRepository.save(student);
}
Page<Student> page =
studentRepository.findAll(PageRequest.of(0,5));
| Parameter | Meaning |
|---|---|
| 0 | Page number |
| 5 | Records per page |
Spring Boot JPA simplifies database operations by providing:
In Spring Boot JPA, an Entity is a Java object that is managed by the JPA persistence context.
When an entity is managed, JPA automatically:
Java Object (Entity)
|
v
Persistence Context (EntityManager)
|
v
Database Table
An Entity is a Java class mapped to a database table.
import jakarta.persistence.*;
@Entity
@Table(name = "students")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
}
| Java Entity | Database |
|---|---|
| Student class | students table |
| id | primary key |
| name | column |
| column |
EntityManager
|
Hibernate (JPA Implementation)
|
Database
In Spring Boot we usually interact through:
JpaRepository
|
Spring Data JPA
|
EntityManager
|
Hibernate
Transient → Persistent → Detached → Removed
Student student = new Student();
student.setName("John");
studentRepository.save(student);
JPA now tracks changes automatically.
student.setName("David");
Hibernate will execute:
UPDATE students SET name='David' WHERE id=1
The entity was previously managed but is no longer attached to the persistence context.
student.setName("Alex"); // not automatically saved
To reattach:
entityManager.merge(student);
studentRepository.delete(student);
DELETE FROM students WHERE id=1
The persistence context is a memory area where JPA manages entities.
Persistence Context --------------------------- | Student id=1 | | Student id=2 | | Student id=3 | ---------------------------
JPA automatically detects changes made to managed entities.
Student student = studentRepository.findById(1L).get();
student.setName("Mike");
At transaction commit:
UPDATE students SET name='Mike' WHERE id=1
@Transactional
public void updateStudent() {
Student student = studentRepository.findById(1L).get();
student.setName("Robert");
}
Start Transaction
|
Load Entity
|
Modify Entity
|
Dirty Checking
|
Commit Transaction
|
Update Database
| Feature | EntityManager | JpaRepository |
|---|---|---|
| Level | Low-level API | High-level abstraction |
| Code required | More | Less |
| Usage | Used internally | Used by developers |
Controller
|
Service
|
Repository (JpaRepository)
|
EntityManager
|
Hibernate
|
Database
Application Code
|
Spring Data JPA Repository
|
EntityManager
|
Hibernate
|
JDBC
|
HikariCP (Connection Pool)
|
Database
Spring Boot automatically handles creating, reusing, and closing JDBC connections.
| Component | Responsibility |
|---|---|
| DataSource | Provides JDBC connections |
| Connection Pool | Reuses database connections |
| Hibernate | Generates and executes SQL |
| EntityManager | Manages persistence context |
| Transaction Manager | Controls transactions |
spring.datasource.url=jdbc:mysql://localhost:3306/springdb spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
Spring Boot automatically creates a DataSource and manages JDBC connections.
Hikari Connection Pool --------------------------- | Connection 1 | | Connection 2 | | Connection 3 | | Connection 4 | ---------------------------
Instead of creating new connections every time, Spring Boot reuses existing ones.
Connection connection = dataSource.getConnection();
PreparedStatement ps =
connection.prepareStatement("SELECT * FROM students");
ResultSet rs = ps.executeQuery();
This code is executed internally by Hibernate. Developers normally do not write it.
@Transactional
public void updateStudent() {
Student student = repository.findById(1L).get();
student.setName("David");
}
Start Transaction
|
Get JDBC Connection from Pool
|
Execute SQL
|
Commit Transaction
|
Return Connection to Pool
| JDBC Step | Handled By |
|---|---|
| Register driver | Spring Boot Auto Configuration |
| Create connection | DataSource |
| Connection pooling | HikariCP |
| Create statement | Hibernate |
| Execute query | Hibernate |
| Map ResultSet to Entity | Hibernate ORM |
| Close connection | HikariCP |
studentRepository.findAll()
|
Spring Data JPA
|
EntityManager
|
Hibernate generates SQL
|
DataSource provides connection
|
HikariCP connection pool
|
JDBC executes query
|
Entities returned