解决dubbo中hessian序列化时Hibernate的延迟加载,以及Set,Map,List集合的解决方案...

一、问题:
hibernate的延迟加载,导致序列化的时候会抛出Hibernate的LazyInitializationException.
还有就是hibernate的Map、List等会被转换为PersistentCollection对象,一般序列化框架没有针对此类的序列化方案。

二、主要应用场景
1、hibernate对象在缓存的时候,进行序列化操作
2、hibernate对象在使用hessian的RPC操作的时候进行序列化。
3、hibernate对象在进行json对象转换的时候。

三、一班的解决方案
使用DTO/VO对象对hibernate对象进行转换,但是缺点也很明显,代码冗余非常大,DTO/VO对象泛滥。

三、现象以及二班的解决方法
1、对于场景1的解决方案(hibernate对象的缓存)
1)将需要延迟加载的对象,都改成非延迟加载。这个其实也很正常,既然需要缓存对象,又何必延迟加载呢?所以这种方案无可厚非。

2、对于场景2的解决方案(RPC的序列化)
RPC的序列化跟转换成json有个最大的不同点,就是此序列化不会调用get方法获取值,就是IO操作,所以3的方案不可用。

本人是在dubbo中用hessian进行序列化的时候碰到的问题,所以就针对此框架来说吧。
其实在上面的问题中已经描述,就是PersistentCollection对象无法识别,那么就增加对此序列化的方法呗。


public class HibernateSerializerFactory extends SerializerFactory {

private HibernateListSerializer listSerializer = new HibernateListSerializer();
private HibernateMapSerializer mapSerializer = new HibernateMapSerializer();
private HibernateBeanSerializer hibernateBeanSerializer = new HibernateBeanSerializer();

@SuppressWarnings("rawtypes")
public Serializer getSerializer(Class cl) throws HessianProtocolException {
if (PersistentMap.class.isAssignableFrom(cl)) {
return mapSerializer;
} else if (AbstractPersistentCollection.class.isAssignableFrom(cl)) {
return listSerializer;
} else if (cl.getSimpleName().contains("_$$_javassist_")) {
return hibernateBeanSerializer;
}
return super.getSerializer(cl);
}

private static class HibernateBeanSerializer implements Serializer {
@Override
public void writeObject(Object obj, AbstractHessianOutput out) throws IOException {
boolean init = Hibernate.isInitialized(obj);

out.writeObject(init ? obj : null);
out.flush();
return;
}
}

private static class HibernateListSerializer implements Serializer {
private CollectionSerializer delegate = new CollectionSerializer();

@SuppressWarnings({"unchecked", "rawtypes"})
public void writeObject(Object obj, AbstractHessianOutput out) throws IOException {
if (Hibernate.isInitialized(obj)) {
delegate.writeObject(new ArrayList((Collection) obj), out);
} else {
delegate.writeObject(new ArrayList(), out);
}
}

}

private static class HibernateMapSerializer implements Serializer {
private MapSerializer delegate = new MapSerializer();

@SuppressWarnings({"unchecked", "rawtypes"})
public void writeObject(Object obj, AbstractHessianOutput out) throws IOException {
if (Hibernate.isInitialized(obj)) {
delegate.writeObject(new HashMap((Map) obj), out);
} else {
delegate.writeObject(new HashMap(), out);
}
}

}
}


dubbo中通过添加配置文件,可以增加自己的序列化工厂。

[img]http://dl2.iteye.com/upload/attachment/0119/9689/1ec07ac6-e1d2-3cab-a15f-83797514589e.png[/img]


3、对于场景3的现象与方案(hibernate进行json对象转换)
1) Hibernate碰到延迟加载的属性访问时如果session被关闭则抛出LazyInitializationException
2) Hibernate中的one-to-many等关联关系在序列化时如果没有控制,则将整个 数据库都有可能被全部序列化
3) 过多的使用DTO/ValueObject解决这个问题。

解决办法:

1、可以使用阿里巴巴的fastjson,对这种一对多或多对一的对象序列化做到了可控性,通过在序列化的时候添加SerializerFeature中的DisableCircularReferenceDetect即可。至于延迟加载可以用OpenSessionInView,这个也只局限于web才可以。

2、对Entity对象生成一个动态代理,拦截getXXXX()方法,如果访问的是延迟加载的属性,则return null,而不抛出LazyInitializationException,递归生成属性的代理,只要碰到未延迟加载的属性,而序列化会自动停止.避免将整个Entity序 列化传播,导致可能序列化整个数据库的问题。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值