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.IDENTITY for 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