GSON 报错HibernateProxy. Forgot to register a type adapter?

来源:互联网 发布:渠道管理 知乎 编辑:程序博客网 时间:2024/06/05 05:52
摘要: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?

使用Gson转换Hibernate对象遇到一个问题,当对象的Lazy加载的,就会出现上面的错误。处理方式摘抄自网上,留存一份以后自己看。

/** * This TypeAdapter unproxies Hibernate proxied objects, and serializes them * through the registered (or default) TypeAdapter of the base class. */public class HibernateProxyTypeAdapter extends TypeAdapter<HibernateProxy> {    public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {        @Override        @SuppressWarnings("unchecked")        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {            return (HibernateProxy.class.isAssignableFrom(type.getRawType()) ? (TypeAdapter<T>) new HibernateProxyTypeAdapter(gson) : null);        }    };    private final Gson context;    private HibernateProxyTypeAdapter(Gson context) {        this.context = context;    }    @Override    public HibernateProxy read(JsonReader in) throws IOException {        throw new UnsupportedOperationException("Not supported");    }    @SuppressWarnings({"rawtypes", "unchecked"})    @Override    public void write(JsonWriter out, HibernateProxy value) throws IOException {        if (value == null) {            out.nullValue();            return;        }        // Retrieve the original (not proxy) class        Class<?> baseType = Hibernate.getClass(value);        // Get the TypeAdapter of the original class, to delegate the serialization        TypeAdapter delegate = context.getAdapter(TypeToken.get(baseType));        // Get a filled instance of the original class        Object unproxiedValue = ((HibernateProxy) value).getHibernateLazyInitializer()                .getImplementation();        // Serialize the value        delegate.write(out, unproxiedValue);    }}

实现上面的类,然后就是使用:

GsonBuilder b = new GsonBuilder();...b.registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY);...Gson gson = b.create();

解释,只是看不懂。

GSON contains a number of TypeAdapterFactory implementations, for various types (primitive types, common types like String or Date, lists, arrays...). Each factory is asked if it is able to serialize a certain Java type (the parameter to create is a TypeToken instead of a Class in order to capture possible information about generic types, which Class does not have). If the factory is able to serialize/deserialize a type, it responds with a TypeAdapter instance; otherwise it responds with null.

HibernateProxyTypeAdapter.FACTORY verifies whether type implements HibernateProxy; in that case, it returns an instance of HibernateProxyTypeAdapter for serialization. The write method is called when an actual object has to be serialized; the adapter extracts the original type of the underlying object, and asks GSON for the standard TypeAdapter for the original type, which generally is a ReflectiveTypeAdapter.

Then it retrieves an instance of the original class, instead of directly using the proxy. This is necessary because ReflectiveTypeAdapter accesses directly to fields, instead of using getters; accessing to the fields of a proxied object does not work, and is a classical Hibernate pitfall.

As a possible performance improvement, the delegate TypeAdapter should be acquired in the create method. I found out that calling getSuperclass() on the proxy Class appears to yield the original base class.

0 0
原创粉丝点击