HibernateProxy异常处理 java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?
这里使用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);
HibernateProxy异常处理 java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?的更多相关文章
- Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?
当我们使用gson 转对象时,并且这个对象中有一些属性是懒加载时如 @Entity @Table(name = "user") public class User { @Id @C ...
- GSON 报错HibernateProxy. Forgot to register a type adapter? 的解决办法
使用Gson转换hibernate对象遇到一个问题,当对象的Lazy加载的,就会出现上面的错误.处理方式摘抄自网上,留存一份以后自己看. 网上找到的解决办法,首先自定义一个类继承TypeAdapter ...
- 关于Mybatis的java.lang.UnsupportedOperationException异常处理
圈住的那行报java.lang.UnsupportedOperationException这个错,这个错的意思是:不支持的操作异常 异常我就不贴了,直接上解决办法吧. 可能我的异常跟大家的不太一样,报 ...
- coding++:Arrays.asList() - java.lang.UnsupportedOperationException异常处理
这个异常遇到了才知道坑这么大,坑爹的方法. private String[] otherUserFromArray = new String[]{“3”, “4”, “发放”}; List<St ...
- java.lang.UnsupportedOperationException: Can't convert to dimension: type=0x12
最近使用Android Studio开发一个新项目,刚做完几个界面,跑在android 5.0上面很正常,因为都是挺简单的布局,本以为应该不存在兼容性问题(Flag啊). 偶然用了一个4.x的实机测试 ...
- java.lang.UnsupportedOperationException: Not supported by BasicDataSource
场景: SpringMVC+Hibernate+Maven 问题: 在src/main/resources 目录中添加hibernate.properties文件, 则如果存在这句hibernate. ...
- Caused by: java.lang.UnsupportedOperationException
对Arrays.asList()返回的List进行操作之后报错Caused by: java.lang.UnsupportedOperationException 让我们来看一下Arrays.asLi ...
- mybatis java.lang.UnsupportedOperationException
mybatis抛出下面的异常: org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exc ...
- 异常:java.lang.UnsupportedOperationException: Manual close is not allowed over a Spring managed SqlSession
使用mybatis-3.2.2.jar + mybatis-spring-1.2.0.jar集成时,报以下异常: 15:42:48.538 [Thread-1] DEBUG o.s.b.f.s.Dis ...
随机推荐
- 【HAOI2007】理想的正方形
[问题描述] 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. [输入] 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行 ...
- Log4Net使用指南(转)
转自:http://www.cnblogs.com/dragon/archive/2005/03/24/124254.html 声明:本文内容主要译自Nauman Leghari的Using log4 ...
- 使用微妙计算PHP脚本执行时间
在PHP中,大多数的时间格式都是以UNIX时间戳表示的,而UNIX时间戳是以s(秒)为最小的计量时间的单位.这对某些应用程序来说不够精确,所以可以调用microtime()返回当前UNIX时间戳和微妙 ...
- net Random 随机数重复的问题
在实际项目中不仅需要随机产生密码字符串,还要一次生成多个.我把生成随机字符串的方法放到for循环中,问题出现了. 生成的字符串,会重复. 经过多方查证,原因在代码. //使用与系统时间相关的种子 Ra ...
- 一分钟让你明白CSS中的盒模型
想必初学者对CSS盒模型总是很困惑吧.下面一分钟让你彻底明白盒模型: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" &q ...
- STM32f103------ADC(DMA)
STM32F10x ADC 技术指标: 分辨率: 12位分辨率 LSB=Vref+ / 2^(12) 转换时间: 采样一次至少14个ADC时钟周期 ,而ADC最高时钟周期为14MHz 选用采样 ...
- POJ2253 Frogger(最短路)
题目链接. 题意: 从0号点,到1号点,找一条能通过的路,使得这条路中的最大的边,比其它所有可能的路中的边都小. 分析: 这题就是按着dijkstra写,写着写着觉得像是prim了. 其中d[n]表示 ...
- BZOJ1715: [Usaco2006 Dec]Wormholes 虫洞
1715: [Usaco2006 Dec]Wormholes 虫洞 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 475 Solved: 263[Sub ...
- BZOJ1511: [POI2006]OKR-Periods of Words
1511: [POI2006]OKR-Periods of Words Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 174 Solved: 92[Su ...
- BZOJ1984: 月下“毛景树”
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 713 Solved: 245[Submit][Status] Descri ...