我有一个REST项目,它使用Gson库来生成和使用我的实体。
但是我遇到了问题。具有通过LAZY提取映射的集合的实体在由Gson序列化时生成LazyInitializationException。
我知道引发异常是因为在关闭hibernate会话时访问了一个集合。但是像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;
}
已经,谢谢!
答案 0 :(得分:2)
这意味着当您的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的映射器以考虑未初始化的持久性集合,以下是一些代码:
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;
}
}
}
}