Java Persistence API (JPA) Basics

Loading

The Java Persistence API (JPA) is a standard for managing relational data in Java applications. It provides a framework for object-relational mapping (ORM), which allows developers to map Java objects to database tables and vice versa. JPA simplifies the interaction with relational databases by abstracting the complexities of SQL queries and database connections.


1. What is JPA?

JPA is a specification in the Java EE (now Jakarta EE) platform that defines how Java objects can be persisted to a relational database. JPA itself is an API (Application Programming Interface) and doesn’t provide the actual implementation of ORM functionality. Instead, it relies on third-party providers like Hibernate, EclipseLink, and OpenJPA to perform the underlying persistence operations.


2. Core Concepts of JPA

Here are the key concepts of JPA that are essential for understanding how it works:

Entities

  • Entity: In JPA, an entity represents a table in the database. Each instance of the entity represents a row in the table.
  • An entity class must be annotated with @Entity and have a primary key, represented by a field annotated with @Id.

Example of an entity class:

import javax.persistence.*;

@Entity
public class Employee {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    private String department;
    private Double salary;

    // Constructors, Getters, Setters
}

Entity Manager

  • EntityManager is the primary interface for interacting with JPA. It is responsible for creating and managing entities, executing queries, and managing transactions.
  • You can use the EntityManager to persist, find, update, and remove entities.

Persistence Unit

  • A Persistence Unit is a set of related entities that can be managed by JPA. The configuration for a persistence unit is specified in the persistence.xml file.
  • This configuration file contains information about the data source (database connection), JPA provider (like Hibernate), and other settings.

Example persistence.xml:

<persistence version="2.0"
    xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    
    <persistence-unit name="myJpaUnit">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.example.Employee</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.show_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

Primary Key

  • Every entity must have a primary key, which is uniquely used to identify each row in the database. The primary key is defined using the @Id annotation.
  • You can configure the strategy for generating primary keys with the @GeneratedValue annotation (e.g., AUTO, IDENTITY, SEQUENCE).

3. CRUD Operations in JPA

JPA allows you to perform Create, Read, Update, and Delete (CRUD) operations using EntityManager. Here’s how these operations are performed:

Create Operation

To create a new entity, you use the EntityManager‘s persist() method. This will insert a new record in the database.

public void createEmployee(Employee employee) {
    EntityManager em = entityManagerFactory.createEntityManager();
    EntityTransaction transaction = em.getTransaction();
    transaction.begin();
    em.persist(employee);
    transaction.commit();
    em.close();
}

Read Operation

To read entities, you can use the find() method to retrieve a specific entity by its primary key or use createQuery() to execute a JPQL query.

public Employee findEmployee(Long id) {
    EntityManager em = entityManagerFactory.createEntityManager();
    return em.find(Employee.class, id);  // Finds an employee by primary key
}

Update Operation

To update an existing entity, you first retrieve the entity using find(), modify its properties, and then commit the changes. You can also use the merge() method to update an entity.

public void updateEmployee(Employee employee) {
    EntityManager em = entityManagerFactory.createEntityManager();
    EntityTransaction transaction = em.getTransaction();
    transaction.begin();
    em.merge(employee);  // Updates the entity in the database
    transaction.commit();
    em.close();
}

Delete Operation

To delete an entity, you retrieve it and then call the remove() method to remove it from the database.

public void deleteEmployee(Long id) {
    EntityManager em = entityManagerFactory.createEntityManager();
    EntityTransaction transaction = em.getTransaction();
    transaction.begin();
    Employee employee = em.find(Employee.class, id);
    if (employee != null) {
        em.remove(employee);  // Deletes the entity
    }
    transaction.commit();
    em.close();
}

4. JPQL (Java Persistence Query Language)

JPA provides its own query language called JPQL (Java Persistence Query Language), which is similar to SQL but works with entities and their attributes rather than tables and columns.

Example of a simple JPQL query:

public List<Employee> findEmployeesByDepartment(String department) {
    EntityManager em = entityManagerFactory.createEntityManager();
    String jpql = "SELECT e FROM Employee e WHERE e.department = :department";
    TypedQuery<Employee> query = em.createQuery(jpql, Employee.class);
    query.setParameter("department", department);
    return query.getResultList();
}

In this example:

  • SELECT e FROM Employee e retrieves all Employee entities.
  • WHERE e.department = :department filters the results by department.

5. Relationships in JPA

JPA supports several types of relationships between entities. These include:

One-to-One

A one-to-one relationship exists when each entity instance is associated with exactly one instance of another entity.

@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToOne
    @JoinColumn(name = "address_id")
    private Address address;
}

One-to-Many

A one-to-many relationship exists when one entity is associated with many instances of another entity.

@Entity
public class Department {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToMany(mappedBy = "department")
    private List<Employee> employees;
}

Many-to-One

A many-to-one relationship is the inverse of one-to-many.

@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;
}

Many-to-Many

A many-to-many relationship exists when each entity instance is associated with many instances of another entity.

@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @ManyToMany
    @JoinTable(
      name = "student_course", 
      joinColumns = @JoinColumn(name = "student_id"), 
      inverseJoinColumns = @JoinColumn(name = "course_id"))
    private List<Course> courses;
}

6. Transactions in JPA

JPA integrates with Java’s transaction management system, making it easy to manage transactional data operations. You can begin, commit, or roll back transactions using EntityTransaction.

Example:

EntityManager em = entityManagerFactory.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
try {
    em.persist(employee);
    transaction.commit();
} catch (RuntimeException e) {
    transaction.rollback();
    throw e;
} finally {
    em.close();
}

Leave a Reply

Your email address will not be published. Required fields are marked *