Почему в JPA класс Entity нельзя объявить как final?

«Почему в JPA класс Entity нельзя объявить как final?» — вопрос из категории Hibernate, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Объявление класса Entity как final нарушает механизм работы JPA-провайдера, который полагается на наследование для создания прокси-объектов. Эти прокси необходимы для двух основных целей:

  1. Ленивая загрузка (Lazy Loading): Когда ассоциация помечена как FetchType.LAZY, вместо реального объекта подставляется прокси, который загружает данные только при первом обращении.
  2. Отслеживание изменений (Dirty Checking): Некоторые провайдеры используют прокси для эффективного определения изменённых полей сущности.

Что происходит, если класс final:

@Entity
public final class Product { // Final класс заблокирует создание прокси
    @Id
    private Long id;
    @ManyToOne(fetch = FetchType.LAZY) // Эта стратегия перестанет работать
    private Category category;
}

При попытке загрузить Product будет выброшено исключение, либо ленивая загрузка будет проигнорирована (принудительно использован EAGER), что может привести к проблемам производительности (N+1 query).

Рекомендация: Избегайте ключевого слова final для классов сущностей и их методов getter/setter, связанных с отображением.