Этап 2 - Entities: связь Java-классов с таблицами
Entity - это Java-класс, объект которого представляет одну строку базы данных. В JPA entity - не любой класс. Это класс, отмеченный @Entity, с идентификатором @Id и правилами, которые позволяют provider создавать, загружать и отслеживать объекты. Самая простая модель такая: один entity class соответствует одной таблице, один entity object соответствует одной строке, а поля соответствуют колонкам.
Что делает класс entity
JPA должна уметь создать объект класса, поэтому entity нужен конструктор без аргументов. Он может быть protected, но должен существовать. У класса должно быть стабильное поле primary key. Entity не стоит делать Java record, потому что JPA entities - изменяемые объекты с lifecycle state. Поля обычно делают private, а application code использует методы или конструкторы, чтобы сохранять корректное состояние объекта.
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true, length = 160)
private String email;
@Column(nullable = false, length = 120)
private String name;
}
@Entity говорит JPA, что этот класс участвует в persistence. Без нее Hibernate воспринимает класс как обычный Java type. @Table настраивает table-level mapping. Если @Table не указать, JPA выведет имя таблицы из имени класса, но в production-проектах явные имена обычно понятнее. @Table может задавать name, schema и unique constraints для нескольких колонок.
Primary key и генерация значений
Primary key уникально идентифицирует одну строку таблицы. В JPA поле primary key помечают @Id. Это идентичность entity с точки зрения базы данных. Две строки не могут иметь одинаковый primary key, а repositories используют его для методов вроде findById и deleteById.
@GeneratedValue описывает, как создается id. IDENTITY означает, что база создает id во время insert, часто через auto-increment или identity column. SEQUENCE использует database sequence, что часто встречается в PostgreSQL и Oracle. AUTO позволяет provider выбрать стратегию под database dialect. TABLE использует отдельную таблицу для id и редко выбирается в новых приложениях, потому что он менее эффективен.
| Стратегия id | Что Hibernate делает до или во время insert | Почему это важно на практике |
|---|---|---|
IDENTITY | Вставляет строку и получает id от database identity column. | Просто понять, но Hibernate обычно хуже batching-ит insert-запросы. |
SEQUENCE | Запрашивает следующий id у database sequence, затем вставляет строку с этим id. | Частый выбор для PostgreSQL и хороший вариант при росте числа insert-операций. |
AUTO | Выбирает стратегию по database dialect и defaults provider-а. | Нормально для демо, но в production лучше явно задавать стратегию. |
TABLE | Хранит и увеличивает ids в отдельной таблице. | В основном legacy; добавляет лишнюю работу базы для генерации id. |
Колонки и Java-типы
@Column настраивает, как поле связано с колонкой базы. name задает имя колонки. nullable = false означает, что колонка не должна принимать NULL. unique = true создает или описывает уникальность для одной колонки. length управляет длиной строковой колонки. Эти настройки не заменяют migrations, но помогают держать Java-модель честной и полезны для schema generation в учебных проектах.
Распространенные Java-типы естественно мапятся в SQL-типы. String становится text или varchar column. Integer, Long, Double мапятся в числовые типы. Boolean мапится в boolean column, если база это поддерживает. LocalDate хранит дату без времени. LocalDateTime хранит дату и время без timezone. Для денег лучше использовать BigDecimal, а не Double, потому что floating-point значения не являются точными.
Поля времени вроде createdAt и updatedAt являются audit fields. createdAt фиксирует момент создания строки. updatedAt фиксирует последнее изменение. В Spring Data JPA аудит можно автоматизировать через @CreatedDate, @LastModifiedDate и @EnableJpaAuditing, но сначала важно понимать смысл этих полей.
Практика
Создай две сущности: User и Product. У User должны быть id, email, name, createdAt, updatedAt. У Product должны быть id, name, price, available, createdAt. Используй явные имена таблиц: users и products. Для обязательных полей поставь nullable = false, а для email добавь уникальность. Запусти приложение с генерацией схемы только в учебном окружении, затем проверь созданные таблицы в PostgreSQL.
Чек-лист понимания
- Могу объяснить связь entity, table, object, row, field и column.
- Понимаю, почему каждой entity нужен
@Id. - Могу выбрать между
IDENTITYиSEQUENCEв типовых случаях. - Понимаю смысл
nullable,uniqueиlength. - Могу описать audit fields и не путать их с бизнес-данными.