Вызов сериализации Gson LazyInitializationException

У меня есть проект REST, который использует библиотеку Gson для создания и использования моих объектов.

Но у меня проблема с этим. Мои сущности с наборами, отображаемыми через LAZY fetch, генерируют исключение *************************** при сериализации Gson.

Я знаю, что исключение возникает из-за того, что коллекция была доступна, когда сеанс hibernate был закрыт.Но как форма Гссона игнорировать неинициализированные ленивые коллекции, возможно ли это?

Класс App является одним из затронутых, где, когда ваше свойство appUsers сериализуется, генерирует эту ошибку:

App.java:

@Entity
@Table(name = "tb_app")
public class App implements Serializable {

 @OneToMany(fetch = FetchType.LAZY, mappedBy = "id.app", cascade = CascadeType.ALL)
 private Set<appuser> appUsers;
}
</appuser>

AppUser.java:

@Entity
@Table(name = "tb_app_user")
@AssociationOverrides({
 @AssociationOverride(name = "id.app", 
 joinColumns = @JoinColumn(name = "id_app", nullable = false)),
 @AssociationOverride(name = "id.user", 
 joinColumns = @JoinColumn(name = "id_user", nullable = false)) })
public class AppUser implements Serializable {

 @EmbeddedId
 private AppUserId id;
}

AppUserId.java:

@Embeddable
public class AppUserId implements Serializable {

 @ManyToOne
 private App app;

 @ManyToOne
 private User user;
}

Уже, спасибо!

1 ответ

Это означает, что когда ваша сериализация JSON происходит, сеанс Hibernate закрывается. Добавление этого в ваш web.xml может помочь (это для JPA, если вы используете чистый Hibernate, для этого тоже есть фильтр Hibernate):

<filter>
 <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
 <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
 <async-supported>true</async-supported>
</filter>



<filter-mapping>
 <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>

Если это не поможет, вам может потребоваться переопределить Gson mapper для учетной записи для неинициализированных постоянных коллекций, вот какой код для этого:

import org.hibernate.collection.internal.AbstractPersistentCollection;

public class PersistentCollectionUtils {
 public boolean isAbstractPersistentCollection(Object object) {
 return object instanceof AbstractPersistentCollection;
 }

 public boolean wasAbstractPersistentCollectionInitialized(Object collection) {
 return ((AbstractPersistentCollection) collection).wasInitialized();
 }

 public boolean isObjectSafeToUse(Object object) {
 return isAbstractPersistentCollection(object) ? 
 wasAbstractPersistentCollectionInitialized(object) :
 true;
 }

 public boolean tryToInitializeCollection(Collection<!--?--> collection) {
 if(collection != null) {
 try {
 collection.iterator().hasNext();
 return true;
 } catch (Exception t) {}
 }
 return false;
 }
}

Ниже приведен пример кода (эта конкретная реализация для Dozer, но вы можете легко перевести его в версию Gson mapper/adapter).

public class PersistentSetMapper implements CustomFieldMapper {

 private PersistentCollectionUtils mapperUtils = new PersistentCollectionUtils();

 @Override
 public boolean mapField(Object source, Object destination, Object sourceFieldValue, ClassMap classMap, FieldMap fieldMapping) {
 // return true => the field has been mapped, no need to map it further
 // return false => the field was not mapped, use downstream mappers

 // check if field is derived from Persistent Collection
 if (!mapperUtils.isAbstractPersistentCollection(sourceFieldValue)) {
 return false;
 }

 // check if field is already initialized
 if (mapperUtils.wasAbstractPersistentCollectionInitialized(sourceFieldValue)) {
 return false;
 } else {
 // if not initialized, try to initialize it
 boolean wasInitialized = mapperUtils.tryToInitializeCollection((Collection<!--?-->) sourceFieldValue);
 if(wasInitialized) {
 return false;
 } else {
 destination = null;
 return true;
 }
 }
 }
}

licensed under cc by-sa 3.0 with attribution.