ORM & Data Access · Java

Hibernate & JPA

JPA is the specification — the contract for how Java code maps to relational tables. Hibernate is the implementation almost everyone uses to satisfy that contract. Together they have powered enterprise Java for two decades and shaped how a generation of engineers thinks about persistence.

JavaJPA SpecPersistence ContextHQL / JPQL
← Back to Database Side
Quick Facts

At a Glance

Core Ideas

  • Entity: a plain Java class annotated with @Entity that maps to a table.
  • EntityManager / Session: the unit-of-work — tracks what you loaded and what changed.
  • Persistence Context: the L1 cache. Same entity loaded twice in one session returns the same instance.
  • JPQL / HQL: object-oriented query language — you query entities, not tables.
  • Dirty Checking: on commit, Hibernate diffs entities against the snapshot it took at load time and writes only the changes.
The Pieces

What You'll Touch

JPA Spec

The Jakarta EE standard. Defines annotations (@Entity, @OneToMany) and the EntityManager API. Vendor-neutral on paper.

Hibernate ORM

The reference implementation. Adds features beyond JPA — filters, envers, multi-tenancy, criteria extensions.

Spring Data JPA

The friendly face. Repository interfaces, derived queries (findByEmailAndStatus), pagination — all on top of JPA.

EclipseLink

The other JPA implementation. Reference for newer spec versions; rare in the wild compared to Hibernate.

Flyway / Liquibase

Schema migrations. Hibernate's hbm2ddl auto-update is for demos; real systems use these.

jOOQ (alternative)

Not JPA — a typed SQL DSL. The escape hatch when JPA's abstraction stops paying its rent.

Why It Wins

What JPA Buys You

Object Graphs Without the Plumbing

An Order with line items, a customer, and a shipping address — load the order and walk the graph. Hibernate fetches what you need, when you ask, and tracks every change. Without an ORM, that's hundreds of lines of ResultSet mapping per aggregate.

Database Portability

Dialects translate the same JPQL to PostgreSQL, MySQL, Oracle, SQL Server. The bigger win in practice is the test suite — H2 in-memory for unit tests, real Postgres in CI, with no app code changing.

The Unit-of-Work Pattern

Inside a transaction, you mutate entities and commit. Hibernate decides the SQL order, batches inserts, defers updates, flushes once. The application code reads like business logic, not like database choreography.

Caching Tiers

L1 (per-session) is automatic. L2 (shared, across sessions, with Ehcache/Infinispan/Hazelcast) caches read-mostly entities. The query cache keys SQL → result IDs. Used carefully, all three cut load by an order of magnitude.

The Sharp Edges

Where People Get Cut

N+1 Queries

Load 50 orders, iterate, touch order.getCustomer() on each — that's 1 + 50 SQL statements. The fix is JOIN FETCH, @EntityGraph, or batch-size hints. The diagnosis is reading SQL logs, every time. This single problem accounts for most "Hibernate is slow" complaints.

LazyInitializationException

You return an entity from a service, the transaction closes, the controller serializes it, and a lazy collection blows up because the session is gone. The fixes — open-session-in-view, DTO projections, fetch joins — each come with their own tradeoffs. Many teams ban entities from crossing service boundaries entirely.

Cascade Surprises

CascadeType.ALL on a relationship means deleting a parent deletes the children — and sometimes the children's children. orphanRemoval = true deletes anything detached from the collection. Both are useful; both have ended careers when applied to the wrong association.

The DTO vs Entity Debate

Should the API return entities directly, or always project to DTOs? Entities are convenient but couple the wire format to the table schema and drag the persistence context along. Most mature codebases land on DTOs at the boundary, entities only inside transactions.

Schema Migrations Are Yours

hibernate.hbm2ddl.auto=update looks magical and is a production landmine — non-deterministic, can't review, can't roll back. Use Flyway or Liquibase. Hibernate generates the schema once for inspiration; humans own the migrations from there.

Patterns

How Teams Actually Use It

  • Spring Data repositories for the 80% — JpaRepository<Order, Long> with derived query methods.
  • JPQL with named queries for the next 15% — anything more complex than a derived name supports.
  • Criteria API for dynamic where-clauses (the search-form problem). Verbose, but type-safe with the metamodel.
  • Native SQL (@Query(nativeQuery=true) or jOOQ) for the last 5% — reporting, window functions, vendor-specific tricks.
  • Read models separate from write models — entities for the transactional side, projections or views for queries.
Continue

Related