Gson序列化抛出LazyInitializationException

时间:2014-05-12 23:49:34

标签: java json hibernate rest gson

我有一个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;
}

已经,谢谢!

1 个答案:

答案 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;
            }
        }
    }
}