Posted on: March 8, 2025 Posted by: rahulgite Comments: 0

What is JPA?

Java Persistence API (JPA) is a specification for managing relational data in Java applications. It provides an abstraction layer for object-relational mapping (ORM) and allows developers to interact with databases using Java objects rather than writing SQL queries manually.


1. Key Features of JPA

  • ORM (Object-Relational Mapping): Maps Java classes to database tables.
  • Annotations-Based Configuration: Uses annotations like @Entity, @Table, and @Column to define mappings.
  • Entity Lifecycle Management: Supports persist, merge, remove, and refresh operations.
  • Query Language (JPQL): Allows querying using JPQL (Java Persistence Query Language) instead of raw SQL.
  • Transaction Management: Works with transactions using @Transactional and EntityManager.
  • Caching Mechanism: Supports first-level and second-level caching to optimize performance.
  • Lazy and Eager Loading: Provides control over when data is fetched.
  • Event Listeners & Callbacks: Supports lifecycle hooks like @PrePersist, @PostPersist for auditing.

2. JPA Components

a. Entity

Entities are Java objects representing database tables.

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

    @Column(name = "name")
    private String name;

    @Column(name = "salary")
    private Double salary;
}

b. EntityManager

The EntityManager is used to interact with the database.

@PersistenceContext
private EntityManager entityManager;

public void saveEmployee(Employee employee) {
    entityManager.persist(employee);
}

c. JPQL (Java Persistence Query Language)

JPQL allows writing SQL-like queries but operates on entity objects.

TypedQuery<Employee> query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.salary > :salary", Employee.class);
query.setParameter("salary", 50000);
List<Employee> results = query.getResultList();

3. JPA Relationships & When to Use @JoinTable and mappedBy

JPA supports various relationships between entities:

a. One-to-One Relationship

@Entity
public class Employee {
    @Id @GeneratedValue
    private Long id;
    
    @OneToOne(mappedBy = "employee")
    private Address address;
}

When to Use mappedBy:

  • Use mappedBy in the non-owning side of the relationship to indicate that the mapping is already defined by the other entity.
  • Helps avoid unnecessary join tables and duplication.

b. One-to-Many Relationship

@Entity
public class Department {
    @Id @GeneratedValue
    private Long id;

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

When to Use mappedBy:

  • Use mappedBy in the non-owning side (Employee should have @ManyToOne private Department department;).
  • Reduces unnecessary join tables.

c. Many-to-Many Relationship

@Entity
public class Student {
    @Id @GeneratedValue
    private Long id;

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

When to Use @JoinTable:

  • Used in @ManyToMany relationships to define a custom join table.
  • Necessary when JPA does not generate an intermediary table automatically.

4. JPA Transactions

JPA transactions are managed using @Transactional in Spring Boot or manually using EntityManager.

@Transactional
public void updateSalary(Long employeeId, Double newSalary) {
    Employee emp = entityManager.find(Employee.class, employeeId);
    emp.setSalary(newSalary);
}

5. JPA Best Practices

  • Use DTOs for large queries instead of returning entity objects.
  • Avoid N+1 query problems by using @EntityGraph or JOIN FETCH.
  • Use caching effectively to reduce database load.
  • Use batch processing for bulk inserts and updates.

6. Common JPA Interview Concepts with Examples

What are the different states of an entity in JPA?

JPA defines four entity states:

  • New (Transient): Object is created but not yet persisted in the database.
  • Managed: Object is associated with an active persistence context.
  • Detached: Object was previously persisted but is now out of the persistence context.
  • Removed: Object is marked for deletion but not yet deleted.

Example:

Employee emp = new Employee(); // New state
entityManager.persist(emp); // Managed state
entityManager.detach(emp); // Detached state
entityManager.remove(emp); // Removed state

How does JPA handle concurrency?

JPA supports two types of locking:

  • Optimistic Locking (@Version): Prevents lost updates using a version field.
  • Pessimistic Locking (PESSIMISTIC_WRITE): Prevents concurrent updates by locking the record.

Example:

@Entity
public class Product {
    @Id
    @GeneratedValue
    private Long id;

    @Version
    private int version;
}

How can you improve JPA query performance?

  • Use indexes on frequently queried columns.
  • Enable second-level caching.
  • Use batch fetching to reduce query count.

What is the difference between merge() and persist()?

  • persist(): Saves a new entity and makes it managed.
  • merge(): Updates an existing entity or creates a new one if not found.

Example:

Employee emp = new Employee();
entityManager.persist(emp); // Saved in database
emp.setName("Updated");
entityManager.merge(emp); // Updates the entity

How can you handle database migrations with JPA?

  • Use Flyway or Liquibase to manage schema changes.
  • Example Flyway migration script:
CREATE TABLE employees (
    id BIGINT PRIMARY KEY,
    name VARCHAR(255),
    salary DECIMAL(10,2)
);

Leave a Comment