Как проверить, инициализирована ли ленивая загруженная коллекция JPA?

У меня есть служба, которая получает объект JPA из внешнего кода. В этой службе я хотел бы выполнить итерацию по лениво загруженной коллекции, которая является атрибутом этого объекта, чтобы увидеть, добавил ли клиент что-то к ней относительно текущей версии в БД.

Однако клиент, возможно, никогда не касался коллекции, поэтому он все еще не инициализирован. Это приводит к хорошо известному

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.SomeEntity.

Конечно, если клиент никогда не касался коллекции, мой сервис не должен проверять его на предмет возможных изменений. Дело в том, что я не могу найти способ проверить, инициализирована ли коллекция или нет. Наверное, я мог бы называть size() на нем, и если он выбрасывает LazyInitializationException, я бы знал, но я стараюсь не зависеть от таких шаблонов.

Есть ли какой-нибудь метод isInitialized()?

Ответ 1

Используете ли вы JPA2?

PersistenceUnitUtil имеет два метода, которые могут использоваться для определения состояния загрузки объекта.

например. существует двунаправленная связь OneToMany/ManyToOne между Организацией и пользователем.

public void test() {
    EntityManager em = entityManagerFactory.createEntityManager();
    PersistenceUnitUtil unitUtil =
        em.getEntityManagerFactory().getPersistenceUnitUtil();

    em.getTransaction().begin();
    Organization org = em.find(Organization.class, 1);
    em.getTransaction().commit();

    Assert.assertTrue(unitUtil.isLoaded(org));
    // users is a field (Set of User) defined in Organization entity
    Assert.assertFalse(unitUtil.isLoaded(org, "users"));

    initializeCollection(org.getUsers());
    Assert.assertTrue(unitUtil.isLoaded(org, "users"));
    for(User user : org.getUsers()) {
        Assert.assertTrue(unitUtil.isLoaded(user));
        Assert.assertTrue(unitUtil.isLoaded(user.getOrganization()));
    }
}

private void initializeCollection(Collection<?> collection) {
    // works with Hibernate EM 3.6.1-SNAPSHOT
    if(collection == null) {
        return;
    }
    collection.iterator().hasNext();
}

Ответ 2

org.hibernate.Hibernate.isInitialized(..)

Я не знаю стандартного решения JPA. Но если вы хотите фактически инициализировать коллекции, вы можете создать метод утилиты и перебрать их (достаточно только одной итерации).

Ответ 3

Как указывает другой плакат, у Hibernate есть метод для этого. Однако для чистого JPA решения нет.