JPA Implementation

About JPA

  • JPA (Java Persistence API) is a Java specification (a set of rules or guidelines).

  • JPA defines:

    • How Java objects (entities) map to relational database tables.

    • How to perform CRUD operations, queries, transaction management, etc.

JPA (Java Persistence API) is defined in JSR (Java Specification Request) documents — initially JSR 220 (EJB 3.0), later evolved into JSR 317 (JPA 2.0), JSR 338 (JPA 2.1), and so on. It standardizes Object-Relational Mapping (ORM), entity management, JPQL (Java Persistence Query Language), criteria queries, etc.

JPA introduces interfaces and annotations like:

  • EntityManager, EntityTransaction, Query

  • Annotations like @Entity, @Table, @Id, @OneToMany, @ManyToOne

About JPA Implementation

  • A JPA Implementation is a real library/framework that implements the contracts defined by the JPA specification.

  • It provides the working code that does:

    • Managing entity life cycles (persist, merge, remove, detach).

    • Translating JPQL (Java Persistence Query Language) into SQL.

    • Managing caching, flushing, dirty checking.

    • Handling transactions.

    • Optimizing database interaction.

Aspect
JPA Specification
JPA Implementation

What it does

Defines "what should be done"

Provides "how it is actually done"

Example

@Entity, EntityManager, @OneToMany, JPQL syntax rules

Hibernate, EclipseLink, OpenJPA, DataNucleus

Why Separate JPA and Implementation?

  • Portability: We can change the JPA implementation (say Hibernate → EclipseLink) without changing much of our Java code.

  • Standardization: Java developers can write one standard code (@Entity, EntityManager) and multiple vendors can compete on performance/features.

  • Loose Coupling: Our code talks to JPA API, and behind the scenes, the implementation does the work.

What a JPA Implementation Must Provide Technically ?

To conform to the JPA specification, a JPA provider (like Hibernate) must implement:

Feature
Description

Persistence Context Management

Handling life cycle states (Transient, Managed, Detached, Removed)

EntityManager

Real class implementing javax.persistence.EntityManager

Persistence Unit Deployment

Understand and parse persistence.xml or Spring Boot configs

Entity Mapping

Convert Java class metadata into SQL DDL (Data Definition Language) and ORM mapping

SQL Generation

Translate JPQL queries and Criteria API calls into actual SQL

Transaction Handling

Support for JTA (Java Transaction API) and resource-local transactions

Caching

Manage first-level (mandatory) and second-level (optional) caches

Flush and Dirty Checking

Auto-detect which fields changed and optimize update SQL

Lazy and Eager Loading

Implement efficient fetching mechanisms according to FetchType

Optimistic and Pessimistic Locking

Implement concurrency control

Callbacks and Listeners

Support @PrePersist, @PostPersist, etc. entity life-cycle callbacks

Architecture Layers Typically Found in a JPA Implementation

Most modern JPA Implementations internally have multi-layered architectures:

Layer
Responsibility

Session/EntityManager Layer

User API entry point, entity management operations.

Persistence Context Layer

Context cache, flush ordering, dirty checking.

SQL Generation Layer

Build and optimize SQL queries from JPQL or Criteria API.

Transaction Layer

Handle transactional demarcation (commit, rollback).

Schema/DDL Layer

Manage schema creation/update/drop based on mappings.

Caching Layer

First-level cache (mandatory) and optional second-level cache integration.

Metadata Layer

Parse and store mappings from annotations/XML.

Database Dialect Layer

Abstracts vendor-specific SQL variations (e.g., MySQL vs Oracle).

Common JPA Implementations

JPA Implementation
Maintained By
Notes

Hibernate

Red Hat

Most popular, default in Spring Boot, rich features.

EclipseLink

Eclipse Foundation

Reference Implementation for JPA. Good integration with Java EE.

Apache OpenJPA

Apache Software Foundation

Less popular today, once used in older Java EE servers.

DataNucleus

Open Source Project

Supports JPA and also other data stores like NoSQL.

Batoo JPA

(Defunct)

Claimed to be faster than Hibernate, now discontinued.

Hibernate is the most dominant, even if you don't specify, Spring Boot picks Hibernate internally as default JPA provider.

EclipseLink is used where Java EE or Jakarta EE compliance is more important (example: Jakarta EE servers like GlassFish).

How to Choose a JPA Implementation ?

Criteria
Decision

Ecosystem Compatibility (Spring Boot)

Hibernate (default and most compatible)

Jakarta EE / Java EE full compliance

EclipseLink

Multi-database (SQL + NoSQL) support

DataNucleus

Very lightweight JPA needs

Older projects may use OpenJPA (rare now)

How to Configure a JPA Implementation in Spring Boot ?

In Spring Boot, "configuring a JPA implementation" means:

  • Deciding which JPA provider (implementation) we want (Hibernate, EclipseLink, etc.).

  • Setting up how it interacts with:

    • our database (MySQL, PostgreSQL, etc.),

    • our entities (@Entity classes),

    • and our application behavior (schema generation, SQL output, transactions, etc.).

Spring Boot auto-configures most of the JPA setup, but we can override and fine-tune it manually.

JPA Provider Selection (By Default)

  • If we add only:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

Hibernate is automatically chosen as the JPA provider.

Why?

  • spring-boot-starter-data-jpa has a transitive dependency on Hibernate (comes with hibernate-core.jar).

  • Spring Boot looks for available providers on the classpath. Hibernate wins by default if found.

If we want another provider (like EclipseLink):

  • Exclude Hibernate from the starter.

  • Add EclipseLink dependency manually.

Example (Maven):

<!-- Starter without Hibernate -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<!-- Add EclipseLink separately -->
<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>eclipselink</artifactId>
    <version>3.0.2</version>
</dependency>

Additionally, we must tell Spring Boot to use a different JpaVendorAdapter.

Configuration in application.properties

Spring Boot uses externalized configuration.

Common JPA-related properties we configure

# Data Source
spring.datasource.url=jdbc:mysql://localhost:3306/yourdb
spring.datasource.username=youruser
spring.datasource.password=yourpass
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# JPA Settings
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.open-in-view=false

Details

Property
Purpose

spring.datasource.*

DB connection properties (URL, username, password, driver).

spring.jpa.database-platform

Force dialect if needed (Hibernate dialect, or EclipseLink equivalent).

spring.jpa.show-sql

Logs generated SQL queries to console.

spring.jpa.hibernate.ddl-auto

Control schema generation: none, validate, update, create, create-drop.

spring.jpa.open-in-view

Controls EntityManager session scope (per transaction vs per web request).

Spring Boot internally configures a JpaVendorAdapter

Implementation
Purpose

HibernateJpaVendorAdapter

Hibernate-specific behaviors.

EclipseLinkJpaVendorAdapter

EclipseLink-specific behaviors.

OpenJpaVendorAdapter

Apache OpenJPA-specific behavior

What Happens Behind the Scenes ?

When Spring Boot starts:

  1. Detects JPA provider on the classpath (Hibernate usually).

  2. Auto-configures:

    • EntityManagerFactory

    • TransactionManager

    • JpaVendorAdapter

  3. Reads application.properties or application.yml

  4. Applies properties to JPA internals.

  5. Starts connection to database.

  6. Scans for @Entity classes automatically if packages are set up properly.

  7. If ddl-auto is update or create, generates schema automatically.

  8. Opens Persistence Contexts for request/transaction scopes.

Last updated