Как проверить, инициализирована ли загруженная коллекция JPA? - PullRequest
46 голосов
/ 29 ноября 2010

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

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

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

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

Ответы [ 4 ]

55 голосов
/ 09 декабря 2010

Вы используете 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();
}
24 голосов
/ 29 ноября 2010
org.hibernate.Hibernate.isInitialized(..)

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

2 голосов
/ 01 декабря 2011

Для eclipselink пользователи приводят коллекцию, к которой вы пытаетесь обратиться, к org.eclipse.persistence.indirection.IndirectList, а затем вызываете ее метод isInstantiated(). Следующая ссылка содержит больше информации:

http://www.eclipse.org/eclipselink/api/1.1/org/eclipse/persistence/indirection/IndirectList.html#isInstantiated.

2 голосов
/ 29 ноября 2010

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

...