On this page
JPA Overview
The Java Persistence API (JPA) is the standard specification for object-relational mapping (ORM) in Java. It defines how Java objects map to relational database tables.
JPA vs Hibernate
| Aspect | JPA | Hibernate |
|---|---|---|
| Type | Specification (JSR 338) | Implementation |
| Annotations | @Entity, @Id, etc. |
JPA + Hibernate extensions |
| Query language | JPQL | HQL (similar to JPQL) |
| Portability | Switch ORM providers | Hibernate-specific features |
Hibernate is the most widely used JPA implementation. Spring Boot uses Hibernate by default.
Core Concepts
Java Object (Entity) ←→ JPA Provider (Hibernate) ←→ Database Table
User.java ORM Engine users table
| Concept | Description |
|---|---|
| Entity | Java class mapped to a table |
| EntityManager | Interface for CRUD operations |
| Persistence Context | First-level cache of managed entities |
| JPQL | Java Persistence Query Language |
| Criteria API | Type-safe query builder |
Basic Entity
@Entity
@Table(name = "books")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 200)
private String title;
@Column(name = "isbn", unique = true)
private String isbn;
private BigDecimal price;
@Temporal(TemporalType.DATE)
private Date publishedDate;
}
EntityManager Operations
EntityManager em = entityManagerFactory.createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
// Persist (INSERT)
Book book = new Book("Clean Code", "978-0132350884");
em.persist(book);
// Find (SELECT)
Book found = em.find(Book.class, 1L);
// Update (automatic dirty checking)
found.setPrice(new BigDecimal("39.99"));
// Remove (DELETE)
em.remove(found);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
Entity Lifecycle
new/transient ──persist()──▶ managed ──remove()──▶ removed
▲ │
│ │ detach()
└──── merge() ◀──────── detached
| State | Description |
|---|---|
| Transient | New object, not associated with persistence context |
| Managed | Tracked by EntityManager; changes auto-flushed |
| Detached | Previously managed, no longer tracked |
| Removed | Scheduled for deletion on flush/commit |
Persistence Unit Configuration
persistence.xml:
<persistence-unit name="myPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.example.Book</class>
<properties>
<property name="jakarta.persistence.jdbc.url"
value="jdbc:postgresql://localhost:5432/mydb"/>
<property name="jakarta.persistence.jdbc.user" value="postgres"/>
<property name="jakarta.persistence.jdbc.password" value="secret"/>
<property name="hibernate.dialect"
value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
With Spring Boot, configure via application.yml instead.
Best Practices
- Keep entities focused — avoid business logic in entity classes
- Use
GenerationType.IDENTITYfor auto-increment PKs - Always use transactions for write operations
- Understand the persistence context to avoid lazy loading exceptions
- Prefer Spring Data JPA over raw EntityManager in Spring applications