1. 程式人生 > >重點技術-20181008-GSON 報錯HibernateProxy. Forgot to register a type adapter?

重點技術-20181008-GSON 報錯HibernateProxy. Forgot to register a type adapter?

摘要: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?

使用Gson轉換Hibernate物件遇到一個問題,當物件的Lazy載入的,就會出現上面的錯誤。處理方式摘抄自網上,留存一份以後自己看。

  1. /**

  2. * This TypeAdapter unproxies Hibernate proxied objects, and serializes them

  3. * through the registered (or default) TypeAdapter of the base class.

  4. */

  5. public class HibernateProxyTypeAdapter extends TypeAdapter<HibernateProxy> {

  6. public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {

  7. @Override

  8. @SuppressWarnings("unchecked")

  9. public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {

  10. return (HibernateProxy.class.isAssignableFrom(type.getRawType()) ? (TypeAdapter<T>) new HibernateProxyTypeAdapter(gson) : null);

  11. }

  12. };

  13. private final Gson context;

  14. private HibernateProxyTypeAdapter(Gson context) {

  15. this.context = context;

  16. }

  17. @Override

  18. public HibernateProxy read(JsonReader in) throws IOException {

  19. throw new UnsupportedOperationException("Not supported");

  20. }

  21. @SuppressWarnings({"rawtypes", "unchecked"})

  22. @Override

  23. public void write(JsonWriter out, HibernateProxy value) throws IOException {

  24. if (value == null) {

  25. out.nullValue();

  26. return;

  27. }

  28. // Retrieve the original (not proxy) class

  29. Class<?> baseType = Hibernate.getClass(value);

  30. // Get the TypeAdapter of the original class, to delegate the serialization

  31. TypeAdapter delegate = context.getAdapter(TypeToken.get(baseType));

  32. // Get a filled instance of the original class

  33. Object unproxiedValue = ((HibernateProxy) value).getHibernateLazyInitializer()

  34. .getImplementation();

  35. // Serialize the value

  36. delegate.write(out, unproxiedValue);

  37. }

  38. }

實現上面的類,然後就是使用:

  1. GsonBuilder b = new GsonBuilder();

  2. ...

  3. b.registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY);

  4. ...

  5. 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.

--------------------- 本文來自 xspwz123 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/xspwz123/article/details/71425545?utm_source=copy