HibernateProxy异常处理 java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class:
2017-12-16 13:04
573 查看
排除策略
最简单的gson转换可以是这样的,但却没有多少实际的作用。切面日志时,一个实体和其他实体存在关联,这时候就需要通过自定义排除策略决定如何转换关联对象,否则可能出现“爆炸式”的json字符串。
Gson gson = new Gson(); int[] ints = {1, 2, 3, 4, 5}; String[] strings = {"abc", "def", "ghi"}; // Serialization gson.toJson(ints); ==> prints [1,2,3,4,5] gson.toJson(strings); ==> prints ["abc", "def", "ghi"]
下面是我定义的一个排除策略的类,能基本满足需求,从内网搬过来的,未测试
package com.lingceng.magic.logutil; import org.apache.commons.lang.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.ExclusionStrategy; import com.google.gson.FieldAttributes; public class TargetStrategy implements ExclusionStrategy { private static Logger log = LoggerFactory.getLogger(TargetStrategy.class); private Class<?> target; private String[] fields; private Class<?>[] clazz; private boolean reverse; public TargetStrategy(Class<?> target) { super(); this.target = target; } @Override public boolean shouldSkipClass(Class<?> class1) { return false; } @Override public boolean shouldSkipField(FieldAttributes fieldattributes) { Class<?> owner = fieldattributes.getDeclaringClass(); Class<?> c = fieldattributes.getDeclaredClass(); String f = fieldattributes.getName(); boolean isSkip = false; if (owner == target) { if (ArrayUtils.contains(fields, f)) { log.debug("fitler field:{} for class:{}", f, owner); isSkip = true; } if (ArrayUtils.contains(clazz, c)) { log.debug("fitler class:{} for class:{}", c, owner); isSkip = true; } if (reverse) { isSkip = !isSkip; } } return isSkip; } public void setFields(String[] fields) { this.fields = fields; } public void setClazz(Class<?>[] clazz) { this.clazz = clazz; } public void setReverse(boolean reverse) { this.reverse = reverse; } }
使用的时候是这样的
TargetStrategy ts = new TargetStrategy(Student.class); //这里表示仅转换Student中的id和name属性 ts.setFields(new String[] {"id", "name"}); ts.setReverse(true); Gson gson = new GsonBuilder().setExcludeStrategy(ts).create(); gson.toJson(teacher);
HibernateProxy异常处理
在使用Hibernate时,那么很可能遇到这样的错误:
java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?
因为gson在转换时是使用的反射机制,当获取的实体对象还在hibernate代理的时候,例如刚通过Id获取到,这时候获取到的便是代理对象HibernateProxy。这和直接调用实体对象的get方法不同,获取对象的属性就不能起作用。
解决的方法便是将代理对象实例化,见下面的代码
/** * 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); } }
使用的时候将该TypeAdapter的Factory注册到GsonBuilder,上面的代码变为
Gson gson = new GsonBuilder().setExcludeStrategy(ts) .registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY) .create(); gson.toJson(teacher);
相关文章推荐
- HibernateProxy异常处理 java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?
- java.lang.UnsupportedOperationException,Can't convert to dimension: type=0x1,TypedArray.java,702
- java.lang.UnsupportedClassVersionError: org/hibernate/HibernateException : Unsupported major.minor..
- Hibernate出现java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.user
- hibernate---java.lang.UnsupportedOperationException: The user must supply a JDBC connection
- Spring+hibernate中的问题解决:java.lang.ClassCastException: $Proxy6 cannot be cast to com.mqEsb.service.imp
- SSH整合时执行hibernate查询报错:java.lang.ClassCastException: com.ch.hibernate.Department_$$_javassist_0 cannot be cast to javassist.util.proxy
- hibernate程序的异常:java.lang.UnsupportedOperationException: The user must supply a JDBC connection
- java.lang.ClassCastException: org.hibernate.impl.QueryImpl cannot be cast to java.util.List
- Caused by: java.lang.UnsupportedOperationException: Can't convert to color: type=0x1
- java.lang.UnsupportedOperationException: Can't convert to integer: type=0x3
- java.lang.UnsupportedOperationException: Can't convert to dimension: type=0x1
- java.lang.ClassCastException: org.hibernate.impl.SessionFactoryImpl cannot be cast to org.springfram
- hibernate---java.lang.UnsupportedOperationException: The user must supply a JDBC connection
- Caused by: java.lang.ClassCastException: org.hibernate.type.StringType cannot be cast to org.hiberna
- hibernate程序的异常:java.lang.UnsupportedOperationException: The user must supply a JDBC connection
- Caused by: java.lang.ClassCastException: org.hibernate.type.StringType cannot be cast to org.hiberna
- Hibernate:java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to co
- java.lang.ClassCastException: org.hibernate.impl.QueryImpl cannot be cast to UserActivity
- hibernate :java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer