Hibernate LazyInitializationException on find () with EIGHTER @ElementCollection



Я получаю org.hibernate.LazyInitializationException: illegal access to loading collection в своем коде JPA - все коллекции стремятся получить - когда объект коллекции также имеет коллекцию.



Не мог бы кто-нибудь помочь мне это исправить?

Я выделил проблему в своем коде JPA следующим определениям @Entity:



(Обратите внимание, я пропускаю инструкции package и import, чтобы сократить код. Некоторые аннотации Ломбока используются, такие как @Data, чтобы означать, что поле имеет геттер / сеттер и @Cleanup, чтобы сделать обычную попытку / перехват закрыть () танец)



@Entity
@Data
public class MyEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

// @ElementCollection(fetch = FetchType.EAGER)
// private Set<String> tags = Sets.newTreeSet();
}

@Entity
@Data
public class MyOtherEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@ManyToMany(fetch = FetchType.EAGER)
private Set<MyEntity> entities = Sets.newHashSet();
}


(я также получаю ту же проблему, если я явно делаю полный @JoinTable, но Hibernate, кажется, генерирует все прекрасно без него - я счастлив оставить его).



Проблема в том, что если я раскомментирую поле "теги" в @MyEntity, то я всегда получаю следующее PersistenceException



Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.LazyInitializationException: illegal access to loading collection
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:828)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:781)


Ниже приводится краткое приложение, которое иллюстрирует эту проблему:

public class JpaQuestion {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.put("hibernate.connection.driver_class", "org.apache.derby.jdbc.EmbeddedDriver");
properties.put("hibernate.connection.url", "jdbc:derby:playground;create=true");
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PlaygroundPU", properties);

populate(emf);

@Cleanup("close") EntityManager em = emf.createEntityManager();
MyOtherEntity other = em.find(MyOtherEntity.class, 1L);
System.out.println(other != null ? other.toString() : "null");
}

public static void populate(EntityManagerFactory emf) {
@Cleanup("close") EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
MyEntity a = new MyEntity();
em.persist(a);
MyOtherEntity other = new MyOtherEntity();
other.getEntities().add(a);
em.persist(other);
em.getTransaction().commit();
}
}


UPDATE: я знаю о LazyInitializationException, когда поле жаждет , но это кажется, потому что load() захватывает ленивую версию сущности. Я использую здесь "найти". Я заметил, что если я выдам запрос JPA (вместо find), то эта проблема исчезнет.



UPDATE: это действительно хорошо работает, если вместо find() я использую запрос типа "SELECT b FROM MyOtherEntity b WHERE b.id = :id". Может быть, find() действительно игнорирует загрузку EAGER! Следовательно, это, скорее всего, ошибка в спящем режиме.



Обновление: я зарегистрировал это как сообщение об ошибке с Hibernate в https://hibernate.onjira.com/browse/HHH-7476

768   4  

4 ответов:

Прежде всего полезно ссылаться на полную трассировку стека: http://pastie.org/4358203

Проблема вызвана вашим вызовом тегов.hashCode () в реализации hashCode () функции MyEntity.

Когда вы используете Hibernate для загрузки экземпляра MyOtherEntity, инициализируется его коллекция MyEntity. Когда MyEntity добавляется к реализации набора в MyOtherEntity, естественно вызывается метод hashCode () (наборы не могут содержать дубликатов. и hashCode () является частью того, как Java проверяет равенство объектов). Затем метод hashCode () MyEntity пытается вызвать hashCode () в коллекции тегов. Коллекция тегов находится в процессе инициализации, что приводит к этой ошибке.

Я думаю, что стоит подумать о вашей реализации hashCode () для MyEntity. Действительно ли ваш прецедент требует, чтобы вы сравнивали значения всех элементов в коллекции тегов для обеспечения равенства объектов?

Подробнее информация по управлению равенством объектов в режиме гибернации является полезным ресурсом:

Https://community.jboss.org/wiki/EqualsAndHashCode

LazyInitializationException-указывает на доступ к незафиксированным данным вне контекста сеанса. Например, при обращении к неинициализированному прокси-серверу или коллекции после закрытия сеанса.

Некоторые вещи, которые вы, возможно, захотите попробовать:

Снято @Cleanup - как a LazyInitializationException обычно это означает, что сеанс гибернации был закрыт, Когда прокси-сервер пытался получить доступ к полю, вы должны попробовать это без них @Cleanup аннотации. Я никогда ими не пользовался я сам, но в документах говорится, что объявление переменной очищается вызовом .close() "конец вашей области видимости".

Конфигурация двойной проверки - все еще нечетная, поскольку вы объявляете FetchType.EAGER для обеих ассоциаций. Вы проверили, что эти варианты действительно используются? Я знаю, что конфигурация иногда может быть немного сложной.

PersistenceContextType - вы можете попробовать установить PersistenceContextType.EXTENDED для вашего EntityManager (я думаю, что TRANSACTION является по умолчанию, может быть неправильно но вы можете попробовать быть уверенным).

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

Я думаю, вы уже знаете "LazyInitializationException overcome" запись Вики?

Проблема в том, что Hibernate игнорирует fetch = FetchType.Жаждущий большинства запросов. Попробуйте добавить @Fetch (FetchMode.Присоединиться) к сущностям.

См.: https://community.jboss.org/wiki/HibernateFAQ-AdvancedProblems#Hibernate_ignores_my_outerjointrue_or_fetchjoin_setting_and_fetches_an_association_lazily_using_n1_selects

Эта ошибка появляется, когда hibernate пытается инициализировать объект и возникает некоторая ошибка.

Ошибка может быть

  1. хэш-код и равенства не реализованы должным образом
  2. Ожидается, что ленивый объект будет зашифрован, но в БД он не зашифрован должным образом
  3. вы находитесь вне контекста сеанса гибернации.

Comments

    Ничего не найдено.