Database Integration with Hibernate
Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.
Persistence Bridge
Why this lesson matters
In Building a RESTful Web Service, our API could accept requests and return responses, but the data was still temporary. Real projects need data to survive restarts, scale beyond one JVM, and support queries.
Today we add the missing production layer: Hibernate, a Java ORM that maps objects to database rows.
By the end, you should be able to explain and design this path:
HTTP Request → Controller → Service → Repository → Hibernate → Database
We will stay focused on database integration. Later, the real-time chat project can reuse this persistence foundation without re-learning it from scratch.

Hibernate Mental Model
ORM in one sentence
Hibernate lets you work with Java objects, while it handles most of the SQL needed to store those objects in relational tables.
Instead of thinking only in rows:
users table
+----+----------+----------------+
| id | username | email |
+----+----------+----------------+
You also think in objects:
User{id=1, username="maya", email="maya@app.com"}
Hibernate sits between both worlds:
Java Entity ←→ Hibernate Session/EntityManager ←→ SQL Database
Key terms
- Entity: a Java class mapped to a database table
- Primary key: the identity of a row/object
- Session / EntityManager: unit that tracks and persists entities
- Transaction: boundary where changes succeed or fail together
- Repository / DAO: your project-facing persistence abstraction
This matches the layered structure you used in the REST lesson: controllers should not directly talk to Hibernate.

Entity Mapping Shape
What entity mapping means
In a real Hibernate project, you usually annotate classes with JPA annotations such as @Entity, @Table, @Id, and @Column.
The idea is simple: describe how a Java class corresponds to a table.
The standalone example below uses tiny custom annotations so you can run it without installing Hibernate. It demonstrates the same mapping concept: class metadata becomes table metadata.
```java
import java.lang.annotation.*;
import java.lang.reflect.*;
public class EntityMappingDemo {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface EntityTable {
String name();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Column {
String name();
boolean id() default false;
}
@EntityTable(name = "users")
static class User {
@Column(name = "id", id = true)
private Long id;
@Column(name = "username")
private String username;
@Column(name = "email")
private String email;
}
public static void main(String[] args) {
Class<User> entityClass = User.class;
EntityTable table = entityClass.getAnnotation(EntityTable.class);
System.out.println("Entity: " + entityClass.getSimpleName());
System.out.println("Table : " + table.name());
System.out.println("Columns:");
for (Field field : entityClass.getDeclaredFields()) {
Column column = field.getAnnotation(Column.class);
if (column != null) {
String marker = column.id() ? " primary key" : "";
System.out.println("- " + field.getName() + " -> " + column.name() + marker);
}
}
}
}
```
Configuration Pieces
What Hibernate needs to connect
A Hibernate integration is not just annotations. It also needs runtime configuration.
Typical project pieces:
src/main/java
com.example.user
User.java
UserRepository.java
UserService.java
src/main/resources
hibernate.cfg.xml
or application.properties
Core settings
Setting Purpose JDBC URL Which database to connect to Username/password Database credentials Dialect SQL flavor, such as PostgreSQL or MySQL Entity packages/classes Which models Hibernate should map Schema strategy Whether Hibernate validates, updates, or creates tablesCommon schema strategy values
-
validate: check mappings against existing schema -
update: attempt to update schema automatically -
create: recreate schema, usually unsafe for real data -
none: do nothing automatically
For serious projects, prefer controlled migrations later. For learning projects, update is often convenient.

Best Layer Boundary
In the layered architecture from the REST lesson, which layer should usually contain direct Hibernate calls such as persist, find, or query execution?
Repository Boundary
Keep Hibernate behind an interface
A repository gives the rest of your project a stable API.
Your service layer should ask for operations like:
save(user)
findById(id)
findByEmail(email)
It should not care whether the implementation uses Hibernate, JDBC, an in-memory map, or a test double.
The example below is executable and uses memory instead of Hibernate, but the boundary is the important part. In a real project, the implementation would call Hibernate inside save and findById.
```java
import java.util.*;
public class RepositoryBoundaryDemo {
static class User {
private final long id;
private final String email;
User(long id, String email) {
this.id = id;
this.email = email;
}
long getId() { return id; }
String getEmail() { return email; }
@Override
public String toString() {
return "User{id=" + id + ", email='" + email + "'}";
}
}
interface UserRepository {
void save(User user);
Optional<User> findById(long id);
}
static class InMemoryUserRepository implements UserRepository {
private final Map<Long, User> users = new HashMap<>();
public void save(User user) {
users.put(user.getId(), user);
System.out.println("Saved user " + user.getId());
}
public Optional<User> findById(long id) {
return Optional.ofNullable(users.get(id));
}
}
public static void main(String[] args) {
UserRepository repository = new InMemoryUserRepository();
repository.save(new User(101, "dev@example.com"));
User found = repository.findById(101).orElseThrow();
System.out.println("Found: " + found);
}
}
```
Transaction Boundary
Transactions protect consistency
A transaction groups database work into one unit:
begin → change data → commit
If something goes wrong:
begin → change data → error → rollback
This matters because real operations often touch multiple rows or tables. For example, creating an order might insert an order row, insert order items, and reduce inventory. You do not want only half of that work saved.
In Hibernate, the transaction boundary usually lives in the service layer or application framework configuration, while the repository performs persistence operations inside that boundary.
The demo below models commit and rollback behavior with plain Java so the lifecycle is visible.
```java
public class TransactionBoundaryDemo {
interface Work {
void run();
}
static class TransactionRunner {
void inTransaction(String name, Work work) {
System.out.println("BEGIN " + name);
try {
work.run();
System.out.println("COMMIT " + name);
} catch (RuntimeException ex) {
System.out.println("ROLLBACK " + name + " because: " + ex.getMessage());
}
}
}
public static void main(String[] args) {
TransactionRunner tx = new TransactionRunner();
tx.inTransaction("create-user", () -> {
System.out.println("Insert user row");
System.out.println("Insert profile row");
});
tx.inTransaction("create-order", () -> {
System.out.println("Insert order row");
throw new RuntimeException("inventory unavailable");
});
}
}
```
Session Truth
True or false: a Hibernate Session or JPA EntityManager should usually be treated as a short-lived unit of work rather than a global singleton shared across the entire application.
Mapping Blank
Fill in the blank: In Hibernate, a Java class mapped to a database table is commonly called an ______.
Integration Checklist
A practical Hibernate integration checklist
When adding Hibernate to a Java project, move in this order:
-
Choose the database
- Example: PostgreSQL, MySQL, H2 for local demos
-
Add dependencies
- Hibernate ORM
- JDBC driver for your database
- JPA API if your stack requires it
-
Create entities
- Use clear IDs
- Keep constructors simple
- Avoid putting controller or HTTP logic in entities
-
Configure Hibernate
- JDBC URL
- credentials
- dialect
- entity scanning
- schema strategy
-
Build repositories
- Hide Hibernate calls behind interfaces
- Return domain objects or
Optional<T>for lookups
-
Use transactions intentionally
- Commit complete work
- Roll back failed work
-
Verify with a smoke run
- Insert one row
- Read it back
- Log the generated SQL if useful
Design takeaway
Hibernate is not just a library you attach to a project. It changes the architecture by giving your domain model persistence, while your repository boundary keeps that persistence from leaking everywhere.
Next, this foundation becomes useful when a real-time project needs users, messages, and durable state.
