🌙 Вопросы интервью по EclipseLink

JPA-провайдер от Eclipse Foundation: кэш, weaving, настройка и отличия от Hibernate

Вопрос EclipseLink 1
Что такое EclipseLink и какое место он занимает в экосистеме JPA?

Ответ: EclipseLink — open-source фреймворк персистентности от Eclipse Foundation. Он вырос из Oracle TopLink (код передан Eclipse в 2007 году) и является эталонной реализацией (reference implementation) спецификации JPA / Jakarta Persistence.

Что входит в проект:
  • JPA — ORM для реляционных баз данных
  • MOXy — JAXB и JSON-привязка объектов
  • SDO и DBWS — работа с данными и веб-сервисами поверх БД
  • Поддержка нереляционных источников (NoSQL) через расширения
Где встречается:
  • Провайдер по умолчанию в GlassFish и Payara
  • Используется в Oracle WebLogic
  • Выбор для проектов на Jakarta EE и там, где важна тесная интеграция с Oracle Database
💡 Важно: как и любой JPA-провайдер, EclipseLink подключается через persistence.xml. Код на чистом JPA (EntityManager, @Entity, JPQL) работает с ним так же, как с Hibernate.
Вопрос EclipseLink 2
В чём основные отличия EclipseLink от Hibernate?
Критерий EclipseLink Hibernate
Статус Эталонная реализация JPA Самая распространённая реализация, по умолчанию в Spring Boot
Кэш второго уровня Общий (shared) кэш включён по умолчанию Выключен, подключается отдельно
Ленивая загрузка to-one Через weaving (изменение байткода) Через прокси, создаваемые в runtime
Отслеживание изменений Может отслеживать изменения атрибутов (через weaving) Сравнение со снимком состояния (dirty checking)
Собственный язык запросов JPQL + Expressions API JPQL (HQL) + Criteria
Конфигурация Свойства eclipselink.* Свойства hibernate.*
Экосистема Jakarta EE, Oracle Spring, широкая поддержка инструментов
💡 Важно: из-за кэша по умолчанию и weaving «тот же» код может вести себя иначе при смене провайдера — например, читать устаревшие данные или загружать to-one связи не лениво.
Вопрос EclipseLink 3
Как подключить EclipseLink и настроить persistence.xml?

Ответ: Нужны зависимость EclipseLink и указание провайдера в persistence unit.

Maven-зависимость: org.eclipse.persistence:org.eclipse.persistence.jpa


<persistence-unit name="my-unit" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>com.example.User</class>

    <properties>
        <property name="jakarta.persistence.jdbc.url"
                  value="jdbc:postgresql://localhost:5432/mydb"/>
        <property name="jakarta.persistence.jdbc.user" value="app"/>
        <property name="jakarta.persistence.jdbc.password" value="secret"/>

        <property name="eclipselink.logging.level" value="INFO"/>
        <property name="eclipselink.logging.level.sql" value="FINE"/>
        <property name="eclipselink.logging.parameters" value="true"/>
    </properties>
</persistence-unit>
                
Полезные свойства:
  • eclipselink.logging.level.sql=FINE + eclipselink.logging.parameters=true — вывод SQL с параметрами
  • jakarta.persistence.schema-generation.database.action (create, drop-and-create) — генерация схемы по стандарту; у EclipseLink также есть eclipselink.ddl-generation
  • eclipselink.target-database — явно задать диалект СУБД
  • eclipselink.weaving — включить, выключить или перейти на статический weaving
💡 Важно: начиная с EclipseLink 3.0 (Jakarta Persistence 3.0) используется пространство имён jakarta.persistence, а не javax.persistence.
Вопрос EclipseLink 4
Что такое weaving и зачем он нужен EclipseLink?

Ответ: Weaving — это изменение байткода классов сущностей (динамически при загрузке или статически при сборке), чтобы добавить в них служебную логику EclipseLink. В отличие от Hibernate, EclipseLink не создаёт для ленивых to-one связей прокси-подклассы.

Что даёт weaving:
  • Ленивая загрузка для @OneToOne и @ManyToOne и для базовых атрибутов (@Basic(fetch = LAZY))
  • Отслеживание изменений на уровне атрибутов (быстрее сравнения снимков)
  • Fetch groups — загрузка подмножества полей
  • Внутренние оптимизации (например, кэширование значений)
Как включить:
  • Java EE / Jakarta EE: сервер приложений делает weaving сам
  • Java SE: агент при запуске — -javaagent:eclipselink.jar
  • Статический weaving при сборке (Maven/Ant-плагин) — не нужен агент, подходит для контейнеров и GraalVM
  • Spring: нужен load-time weaver или статический weaving
💡 Частая проблема: без weaving ленивая загрузка to-one связей не работает — они загружаются сразу (eager), и приложение неожиданно делает больше запросов. Коллекции остаются ленивыми и без weaving.
Вопрос EclipseLink 5
Как устроен общий кэш (shared cache) EclipseLink?

Ответ: В EclipseLink есть кэш второго уровня (shared cache), и он включён по умолчанию для сущностей. Объекты, прочитанные одним EntityManager, кладутся в общий кэш EntityManagerFactory и используются другими без обращения к БД.


@Entity
@Cache(
    type = CacheType.SOFT,            // тип хранения
    size = 1000,                      // размер кэша
    expiry = 600000,                  // время жизни, мс
    coordinationType = CacheCoordinationType.INVALIDATE_CHANGED_OBJECTS
)
public class Product { ... }

@Entity
@Cacheable(false)                     // отключить кэш для этой сущности
public class Account { ... }
                
Управление кэшем:
  • jakarta.persistence.sharedCache.mode — ALL, NONE, ENABLE_SELECTIVE, DISABLE_SELECTIVE
  • Для запроса: jakarta.persistence.cache.retrieveMode = BYPASS (не читать из кэша) и eclipselink.refresh = true (обновить из БД)
  • Очистка: emf.getCache().evictAll()
  • Cache coordination — синхронизация кэшей между узлами кластера
💡 Главный риск: если данные меняются в обход приложения (другим сервисом или прямым SQL), кэш может отдавать устаревшие значения. Решение: задать expiry, отключить кэш для таких сущностей или использовать @Cache(alwaysRefresh = true).
Вопрос EclipseLink 6
Как избежать проблемы N+1 в EclipseLink?

Ответ: Стандартные способы JPA работают: JOIN FETCH в JPQL и entity graph. Дополнительно у EclipseLink есть собственные подсказки и аннотации для пакетной загрузки.


// стандартный JPQL
em.createQuery(
    "SELECT o FROM Order o JOIN FETCH o.items", Order.class)
  .getResultList();

// подсказка EclipseLink: загрузить items отдельным запросом для всех заказов сразу
em.createQuery("SELECT o FROM Order o", Order.class)
  .setHint("eclipselink.batch", "o.items")
  .setHint("eclipselink.batch.type", "IN")   // JOIN, EXISTS или IN
  .getResultList();

// на уровне маппинга
@OneToMany(mappedBy = "order")
@BatchFetch(BatchFetchType.IN)
private List<OrderItem> items;
                
  • eclipselink.join-fetch и @JoinFetch — загрузка через JOIN
  • eclipselink.batch и @BatchFetch — пакетная загрузка вторым запросом
💡 Совет: batch часто лучше JOIN FETCH для нескольких коллекций: он не умножает строки результата.
Вопрос EclipseLink 7
Какие собственные аннотации и возможности есть у EclipseLink?

Ответ: Помимо стандартного JPA, EclipseLink предоставляет расширения в пакете org.eclipse.persistence.annotations:

Возможность Для чего
@Cache Тонкая настройка кэша сущности
@Convert, @ObjectTypeConverter Конвертация значений между полем и колонкой
@AdditionalCriteria Дополнительное условие, автоматически добавляемое ко всем запросам (например, фильтр «мягкого удаления»)
@Multitenant Мультиарендность: разделение данных арендаторов в одной схеме
@HistoryPolicy Хранение истории изменений строк
@BatchFetch, @JoinFetch Стратегии загрузки связей
@Customizer Программная настройка дескрипторов сущности
Хранимые процедуры, PL/SQL, иерархические запросы Oracle Расширенная работа с Oracle Database

@Entity
@AdditionalCriteria("this.deleted = false")
public class Document {
    @Id Long id;
    boolean deleted;
}
// em.createQuery("SELECT d FROM Document d") автоматически добавит условие deleted = false
                
💡 Важно: такие аннотации не переносятся на другие провайдеры, это привязка к EclipseLink.
Вопрос EclipseLink 8
Какая внутренняя архитектура у EclipseLink: Session, UnitOfWork и EntityManager?

Ответ: Внутри JPA-слой EclipseLink построен поверх собственного ядра, унаследованного от TopLink.

Понятие JPA Внутренний аналог EclipseLink
EntityManagerFactory ServerSession — общая сессия с пулом соединений и общим кэшем
EntityManager Обёртка над клиентской сессией и UnitOfWork
Контекст персистентности UnitOfWork — копирует объекты из общего кэша в рабочую копию и при commit записывает изменения

Из EntityManager можно получить родные объекты:


JpaEntityManager jpaEm = em.unwrap(JpaEntityManager.class);
UnitOfWork uow = jpaEm.getUnitOfWork();
Session session = jpaEm.getServerSession();
                
💡 Важно: на собеседованиях полезно знать идею: изменения делаются в копии объекта, а общий кэш обновляется только после успешного commit.
Вопрос EclipseLink 9
Как использовать EclipseLink со Spring и Spring Boot?

Ответ: Spring поддерживает EclipseLink через EclipseLinkJpaVendorAdapter, но Spring Boot по умолчанию настроен на Hibernate, поэтому автоконфигурацию нужно заменить вручную.


@Configuration
public class JpaConfig {

    @Bean
    LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource ds) {
        var em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(ds);
        em.setPackagesToScan("com.example.domain");
        em.setJpaVendorAdapter(new EclipseLinkJpaVendorAdapter());

        Map<String, Object> props = new HashMap<>();
        props.put("eclipselink.weaving", "false");           // или настроить weaving
        props.put("eclipselink.logging.level.sql", "FINE");
        em.setJpaPropertyMap(props);
        return em;
    }

    @Bean
    PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }
}
                
На что обратить внимание:
  • В зависимостях нужно исключить Hibernate из spring-boot-starter-data-jpa
  • Spring Data JPA работает поверх любого провайдера, репозитории остаются теми же
  • Weaving: либо отключить (eclipselink.weaving=false) и принять eager для to-one, либо подключить агент или статический weaving
  • Часть возможностей Spring Boot (например, свойства spring.jpa.hibernate.*) работает только с Hibernate
Вопрос EclipseLink 10
Какие типы запросов поддерживает EclipseLink?

Ответ:

  • JPQL — стандартный язык запросов JPA, с рядом расширений EclipseLink (например, функция FUNCTION('...') для вызова функций БД)
  • Criteria API — типобезопасное построение запросов
  • Native SQL — createNativeQuery
  • Expressions API — собственный объектный API запросов EclipseLink: ExpressionBuilder
  • Именованные запросы — @NamedQuery, @NamedNativeQuery
  • Хранимые процедуры — @NamedStoredProcedureQuery

// Expressions API
ExpressionBuilder b = new ExpressionBuilder();
Expression e = b.get("name").equal("Ann").and(b.get("age").greaterThan(18));

ReadAllQuery query = new ReadAllQuery(User.class, e);
List<User> users = (List<User>) uow.executeQuery(query);
                
Подсказки запросов (query hints):
  • eclipselink.cache-usage — как использовать кэш
  • eclipselink.refresh — перечитать из БД
  • eclipselink.query-results-cache — кэш результатов запроса
  • eclipselink.read-only — объекты не отслеживаются на изменения
Вопрос EclipseLink 11
Какие типичные проблемы возникают при работе с EclipseLink?

Ответ:

Проблема Причина и решение
Устаревшие данные при чтении Shared cache: данные изменили вне приложения. Использовать expiry, @Cacheable(false) или eclipselink.refresh
Ленивая загрузка to-one не работает Weaving не включён. Настроить агент, статический weaving или смириться с eager
Ошибка запуска из-за классов сущностей Сущность не указана в persistence.xml в Java SE: добавить <class> или <exclude-unlisted-classes>false</exclude-unlisted-classes>
Лишние запросы (N+1) Использовать JOIN FETCH, eclipselink.batch, @BatchFetch
Разное поведение после перехода с Hibernate Различия в кэше, flush, weaving и значениях по умолчанию. Проверять тестами на реальной БД
Нет SQL в логах Включить eclipselink.logging.level.sql=FINE
Вопрос EclipseLink 12
Когда стоит выбрать EclipseLink, а когда Hibernate?
EclipseLink подходит, когда:
  • Приложение работает на GlassFish, Payara или WebLogic, где он идёт по умолчанию
  • Нужна тесная интеграция с Oracle (хранимые процедуры, PL/SQL, иерархические запросы)
  • Требуются мультиарендность, история изменений или общий кэш из коробки
  • Нужна эталонная реализация спецификации Jakarta Persistence
Hibernate подходит, когда:
  • Проект на Spring Boot — автоконфигурация и документация рассчитаны на Hibernate
  • Нужна самая широкая поддержка сообщества, инструментов и примеров
  • Нужна лёгкая ленивая загрузка без настройки weaving
💡 Вывод: если вы пишете на чистом JPA и не используете расширения провайдера, замена одного на другой возможна, но на практике расширения (@Cache, @Formula, свойства eclipselink.*/hibernate.*) быстро привязывают проект к выбранной реализации.