您的位置:首页 > 编程语言 > Java开发

HibernateProxy异常处理 java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class:

2017-12-16 13:04 573 查看



这里使用google的Gson包做JSON转换,因为较早的1.4版本的FieldAttributes类中没有getDeclaringClass()这个方法,这个方法是获取field所属的类,在我的排除策略中会用到。

排除策略 

  最简单的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);


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐