Gymterview
junior

Основные аннотации маппинга сущностей

Аннотации JPA определяют, как Java-классы и поля маппятся на таблицы и столбцы.

Пример полного маппинга сущности
@Entity                                    // класс — JPA-сущность
@Table(name = "users",                     // таблица в БД
       uniqueConstraints = @UniqueConstraint(columnNames = "email"),
       indexes = @Index(columnList = "name"))
public class User {

    @Id                                    // первичный ключ
    @GeneratedValue(strategy = GenerationType.IDENTITY) // автоинкремент
    private Long id;

    @Column(name = "user_name",            // имя столбца
            nullable = false,              // NOT NULL
            length = 100)                  // VARCHAR(100)
    private String name;

    @Column(unique = true, nullable = false)
    private String email;

    @Enumerated(EnumType.STRING)           // enum как строка (не ordinal!)
    @Column(nullable = false)
    private UserStatus status;

    @Temporal(TemporalType.TIMESTAMP)      // для java.util.Date (не нужен для LocalDateTime)
    private Date createdAt;

    @Lob                                   // BLOB/CLOB — для больших объектов
    private String description;

    @Transient                             // не маппится в БД
    private String temporaryField;

    @Embedded                              // встраиваемый объект
    private Address address;

    @Version                               // оптимистичная блокировка
    private Long version;
}

@Embeddable                                // встраиваемый компонент (без своей таблицы)
public class Address {
    private String city;
    private String street;

    @Column(name = "zip_code")
    private String zipCode;
}

Краткая таблица аннотаций

Аннотация Назначение
@Entity Маркирует класс как JPA-сущность
@Table Настройка таблицы (имя, уникальные ограничения, индексы)
@Id Первичный ключ
@GeneratedValue Стратегия генерации ID
@Column Настройка столбца (имя, nullable, unique, length)
@Enumerated Маппинг enum (STRING или ORDINAL)
@Temporal Тип для java.util.Date
@Lob Большие объекты (BLOB, CLOB)
@Transient Поле не маппится в БД
@Embedded / @Embeddable Встраиваемый объект без собственной таблицы
@Version Поле для оптимистичной блокировки

Важное

  • @Entity обязательна; класс должен иметь конструктор без аргументов и @Id
  • @Column необязательна — без неё поле маппится по имени
  • @Enumerated(EnumType.STRING) — всегда используйте STRING, не ORDINAL (добавление значения в enum сломает данные)
  • @Embedded / @Embeddable — способ декомпозиции сущности без создания отдельной таблицы

Частые ошибки

  • @Enumerated(EnumType.ORDINAL) — при изменении порядка элементов enum данные в БД станут некорректными
  • Отсутствие @Version — без оптимистичной блокировки потерянные обновления (lost updates) неизбежны при конкурентном доступе
  • @Column(nullable = false) без NOT NULL в БД — аннотация влияет только на DDL-генерацию; если БД уже создана через миграции, ограничение нужно добавлять в миграции
  • Маппинг boolean@Column — по умолчанию маппится в BIT/BOOLEAN, но в Oracle нет BOOLEAN; нужен @Column(columnDefinition = "NUMBER(1)")

Как используется в 2026

  • Hibernate 6.x поддерживает Java Records как @Embeddable — удобнее для Value Objects
  • @JdbcTypeCode(SqlTypes.JSON) — нативная поддержка JSON-столбцов в Hibernate 6
  • Temporal API (LocalDate, LocalDateTime) маппится без @Temporal начиная с JPA 2.2
  • @SoftDelete (Hibernate 6.4) — встроенная поддержка мягкого удаления

На собеседовании: минимальный набор, который нужно знать: @Entity, @Table, @Id, @GeneratedValue, @Column, @Enumerated(STRING). Интервьюер часто спрашивает про ORDINAL vs STRING — правильный ответ всегда STRING. Бонус — упомянуть @Version для оптимистичной блокировки и @Embeddable для Value Objects.