Methods to interact with Database

flowchart LR
SDJPA["Spring Data JPA"]

Methods --> JPA
Methods --> Hibernate
Methods --> SDJPA

JPA --> JPQL
JPA --> EntityManager
JPA --> Criteria

Hibernate --> HQL
Hibernate --> Session

SDJPA --> Repository
SDJPA --> Specification
SDJPA --> QueryDsl

JPA

  • Jakarta Persistence API (formerly Java Persistence API)
    • package names: javax.*
  • In 2019 renamed to Jakarta Persistence
    • package names: jakarta.*
  • Refer Java History

EntityManager

  • jakarta.persistence.EntityManager
public interface EntityManager extends AutoCloseable {}
  • JPA interface used to interact with the persistence context
  • Low-level, versatile, but verbose and less type-safe
  • provides methods to create and execute queries using”
    • JPQL
    • native SQL
    • Criteria
List<User> users = entityManager.createNativeQuery("SELECT * FROM User", User.class).getResultList();

JPQL

  • org.springframework.data.jpa.repository.Query
  • Java Persistence Query Language
  • We use @Query
  • For native queries we use @Query("...", native=true)
  • Can be executed using:
    • EntityManager
    • @NamedQuery
    • Spring Data JPA Repository @Query

Criteria

  • jakarta.persistence.criteria.CriteriaQuery
  • Part of JPA
  • nice clean object oriented API
  • Can detect errors in compile time
  • JPQL and Criteria have same efficiency and performance
  • Criteria is more flexible and provide better support for writing dynamic queries as compared to HQL and JPQL
  • Disadvantage: Criteria does not support native queries
  • CriteriaBuilder is used to build CriteriaQuery objects
  • Predicate is used to construct clauses which can be used in CriteriaQuery#where

Hibernate

Session

  • org.hibernate.Session
public interface Session extends SharedSessionContract, EntityManager {}
  • It is specific to Hibernate
  • It extends EntityManager
  • EntityManager will invoke Session behind the hood if implementation is hibernate

HQL

  • org.hibernate.annotations.NamedQuery
  • Hibernate Query Language
  • We use @NamedQuery
  • For native queries we use @NamedNativeQuery
  • Disadvantage:
    • Hibernate specific
    • code’s unreadability
  • Can be executed using:
    • Session.createQuery or EntityManager
    • @NamedQuery

Spring Data JPA

Repository

  • https://docs.spring.io/spring-data/jpa/reference/repositories/definition.html
  • Interfaces:
    • JpaRepositry — CRUD + pagination + sorting + flush persistence/delete record in batch etc., returns List<>
    • PagingAndSortingRepository — CRUD + pagination + sorting
    • CrudRepository — Supports only CRUD, returns Iterable<>
    • ListCrudRepository — returns List<>
    • ReactiveCrudRepository — Flux Mono
    • RxJava3CrudRepository — RxJava

Specification

public interface Specification<T> extends Serializable {}
  • It is an Interface which is part of Spring Data JPA
  • while Criteria is part of JPA
  • It is based on Domain Driven Design book by Eric Evans
  • It is developed to define reusable Predicate and use Criteria API in type-safe way
  • Disadvantage: Specification does not support native queries
  • You need to have JpaSpecificationExecutor on your repository
interface CustomerRepository extends JpaRepository<Customer>, JpaSpecificationExecutor {
  // Your query methods here
}
  • Use
public CustomerSpecifications {
 
  public static Specification<Customer> customerHasBirthday() {
    return new Specification<Customer> {
      public Predicate toPredicate(Root<T> root, CriteriaQuery query, CriteriaBuilder cb) {
        return cb.equal(root.get(Customer_.birthday), today);
      }
    };
  }
}
 
customerRepository.findAll(hasBirthday());

Querydsl

interface CustomerRepository extends JpaRepository<Customer>, QueryDslPredicateExecutor {
  // Your query methods here
}
  • Use
BooleanExpression customerHasBirthday = customer.birthday.eq(today);
BooleanExpression isLongTermCustomer = customer.createdAt.lt(today.minusYears(2));
customerRepository.findAll(customerHasBirthday.and(isLongTermCustomer));