Что такое JPA в Java?
JPA (Java Persistence API) — это стандарт Java для работы с реляционными базами данных через объекты. Вместо того чтобы вручную писать SQL-запросы, разработчик работает с обычными Java-классами, а JPA автоматически преобразует их в записи таблиц базы данных.
Проще говоря:
- без JPA вы работаете с таблицами и SQL;
- с JPA вы работаете с объектами Java, а JPA сама преобразует их в SQL-запросы.
Начиная с перехода Java EE в Jakarta EE спецификация официально называется Jakarta Persistence, однако большинство разработчиков по-прежнему используют привычное название JPA.
Основная идея JPA
Предположим, имеется таблица базы данных:
CREATE TABLE Users
(
Id INT PRIMARY KEY,
Name VARCHAR(100),
Age INT
);
Без JPA пришлось бы самостоятельно писать SQL-запросы для чтения, изменения и удаления данных.
С использованием JPA создается обычный Java-класс:
@Entity
@Table(name = "Users")
public class User {
@Id
private int id;
private String name;
private int age;
// getters/setters
}
Теперь каждая строка таблицы автоматически представляется объектом класса User.
Например:
User user = new User();
user.setId(1);
user.setName("John");
user.setAge(25);
Что умеет JPA?
JPA автоматически выполняет большинство операций с базой данных.
Создание записи
entityManager.persist(user);
Эквивалентный SQL:
INSERT INTO Users (...)
Получение записи
User user = entityManager.find(User.class, 1);
Эквивалентный SQL:
SELECT *
FROM Users
WHERE Id = 1;
Удаление записи
entityManager.remove(user);
Эквивалентный SQL:
DELETE
FROM Users
WHERE Id = 1;
Изменение записи
Достаточно изменить поле объекта:
user.setAge(30);
После завершения транзакции JPA самостоятельно выполнит:
UPDATE Users
SET Age = 30
WHERE Id = 1;
JPA — это не библиотека
Важно понимать, что JPA не является готовой библиотекой. Это лишь спецификация, содержащая набор интерфейсов и правил.
Поэтому необходима библиотека, которая реализует эту спецификацию.
Наиболее популярные реализации:
| Реализация | Описание |
|---|---|
| Hibernate ORM | Самая распространенная реализация JPA. |
| EclipseLink | Официальная эталонная реализация спецификации. |
| Apache OpenJPA | Реализация от Apache Foundation. |
На практике подавляющее большинство проектов используют Hibernate.
JPA и Hibernate
Очень часто эти понятия путают.
JPA — это интерфейс (спецификация), а Hibernate — одна из его реализаций.
JPA
↑
│ интерфейс
│
Hibernate
↑
│ реализация
│
PostgreSQL
MySQL
Oracle
SQL Server
Например:
EntityManager em = ...;
EntityManager — это интерфейс JPA, но его методы фактически выполняет Hibernate.
Основные аннотации JPA
@Entity
Помечает класс как сущность, которая будет храниться в базе данных.
@Entity
public class User
{
}
@Table
Позволяет указать имя таблицы.
@Table(name = "Users")
Если аннотация отсутствует, таблица обычно получает имя класса.
@Id
Обозначает первичный ключ.
@Id
private Long id;
@GeneratedValue
Настраивает автоматическую генерацию значения первичного ключа.
@Id
@GeneratedValue
private Long id;
@Column
Позволяет задать имя столбца и дополнительные параметры.
@Column(name = "user_name")
private String name;
@Transient
Поле не сохраняется в базе данных.
@Transient
private int ageInMonths;
@Enumerated
Используется для хранения перечислений (enum).
public enum Status
{
NEW,
ACTIVE,
BLOCKED
}
@Enumerated(EnumType.STRING)
private Status status;
Связи между сущностями
JPA автоматически поддерживает отношения между таблицами.
Например, один пользователь может иметь несколько заказов.
@OneToMany
private List<Order> orders;
И обратная связь:
@ManyToOne
private User user;
Поддерживаются четыре основных типа отношений:
- One-to-One (@OneToOne)
- One-to-Many (@OneToMany)
- Many-to-One (@ManyToOne)
- Many-to-Many (@ManyToMany)
EntityManager
Главным объектом JPA является EntityManager.
Через него выполняется практически вся работа с базой данных.
EntityManager em;
Основные методы:
| Метод | Назначение |
|---|---|
| persist() | сохранить объект |
| find() | найти объект |
| remove() | удалить объект |
| merge() | обновить объект |
| createQuery() | выполнить запрос |
JPQL
JPQL (Java Persistence Query Language) — язык запросов JPA.
Он похож на SQL, но работает не с таблицами, а с Java-объектами.
SQL:
SELECT *
FROM Users;
JPQL:
SELECT u
FROM User u;
Еще один пример:
SELECT u
FROM User u
WHERE u.age > 18;
JPA самостоятельно преобразует этот запрос в SQL.
Жизненный цикл Entity
Каждая сущность проходит несколько состояний:
Transient
↓
persist()
↓
Managed
↓
remove()
↓
Removed
Transient — объект существует только в памяти.
Managed — объект находится под управлением JPA, и все изменения автоматически отслеживаются.
Removed — объект помечен для удаления из базы данных.
Полный пример
Описание сущности:
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
}
Сохранение объекта:
EntityManager em = ...;
em.getTransaction().begin();
User user = new User();
user.setName("Alice");
em.persist(user);
em.getTransaction().commit();
После выполнения транзакции в таблице появится новая запись.
JPA в Spring
В приложениях Spring редко работают напрямую с EntityManager.
Обычно используют интерфейсы репозиториев:
public interface UserRepository
extends JpaRepository<User, Long>
{
}
После этого становятся доступны готовые методы:
userRepository.save(user);
User user = userRepository
.findById(1L)
.orElse(null);
userRepository.delete(user);
Spring Data JPA использует JPA, а JPA, в свою очередь, использует одну из реализаций, чаще всего Hibernate.
Преимущества JPA
- значительно уменьшает количество SQL-кода;
- позволяет работать с привычными Java-объектами;
- не зависит от конкретной реализации;
- удобно описывает связи между сущностями;
- автоматически отслеживает изменения объектов.
Недостатки JPA
- необходимо понимать жизненный цикл сущностей;
- автоматически создаваемый SQL не всегда оптимален;
- неправильная настройка связей может привести к большому количеству лишних запросов (проблема N+1);
- для сложной аналитики иногда проще использовать обычный SQL.
Заключение
JPA представляет собой стандартный слой между Java-приложением и реляционной базой данных. Разработчик описывает сущности и их взаимосвязи, а JPA автоматически преобразует операции над объектами в SQL-запросы.
В современных Java-проектах наиболее распространенной связкой является Spring Data JPA + Hibernate, позволяющая свести к минимуму объем шаблонного кода при работе с базой данных.
