我有一个 REST 项目,它使用 Gson 库来生成和使用我的实体。
但我对此有疑问。通过 LAZY fetch 映射集合的实体在由 Gson 序列化时会生成 LazyInitializationException。
我知道引发异常是因为在 hibernate session 关闭时访问了集合。但是就像 Gson 的一种形式忽略未初始化的惰性集合一样,这可能吗?
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.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;
}
已经,谢谢!
最佳答案
这意味着当您的 JSON 序列化发生时,您的 Hibernate session 将关闭。将其添加到您的 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 的映射器来处理未初始化的持久集合,下面是一些代码:
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 的映射器/适配器版本)。
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;
}
}
}
}
关于java - Gson序列化抛出LazyInitializationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23620716/