hibernate延迟加载:使用动态代理解决Hibernate序列化 避免延迟加载问题.

  在使用Ajax: Hibernate Entity => json, Flex RemoteObject: Hibernate Entity => ActionScript Object过程,经常碰到如下问题:

  问题:

  1.Hibernate碰到延迟加载属性访问时如果session被关闭则抛出LazyInitializationException

  2.Hibernate中one-to-many等关联关系在序列化时如果没有控制,则将整个数据库都有可能被全部序列化

  3.过多使用DTO/ValueObject解决这个问题.

  解决办法:

  对Entity对象生成个动态代理,拦截getXXXX思路方法,如果访问是延迟加载属性,则 null,而不抛出LazyInitializationException,递归生成属性代理,只要碰到未延迟加载属性,而序列化会自动停止.避免将整个Entity序列化传播,导致可能序列化整个数据库问题.

  类似解决方案:

  dwr中HibernateConverter,在序列化时如上类似,碰到延迟加载属性自动停止convert工作.而HibernateBeanSerializer则劳永逸,无论object => json都可以工作.

  使用用例:

  Java代码

//role为原始对象  
role = (Role)roleDao.getById(  Long( 1 ));  
//生成动态代理proxyRole,访问延迟加载属性将 null  
Role proxyRole = (Role)  HibernateBeanSerializer<Role>(role).getProxy;  
assertNotNull(role.getResource);   
assertNull(proxyRole.getResource); //延迟加载,为null  
Hibernate.initialize(role.getResource); //抓取进来  
assertNotNull(proxyRole.getResource); //不为null  
//role为原始对象
role = (Role)roleDao.getById( Long(1));
//生成动态代理proxyRole,访问延迟加载属性将 null
Role proxyRole = (Role) HibernateBeanSerializer<Role>(role).getProxy;
assertNotNull(role.getResource); 
assertNull(proxyRole.getResource); //延迟加载,为null
Hibernate.initialize(role.getResource); //抓取进来
assertNotNull(proxyRole.getResource); //不为null


  源码.

  Java代码

package cn.org.rapid_framework.util;  
import java.lang.reflect.Modier;  
import java.util.ArrayList;  
import java.util.Collection;  
import java.util.LinkedHashMap;  
import java.util.LinkedHashSet;  
import java.util.List;  
import java.util.Map;  
import java.util.Set;  
import org.aopalliance.ercept.MethodInterceptor;  
import org.aopalliance.ercept.MethodInvocation;  
import org.hibernate.Hibernate;  
import org.hibernate.collection.PersistentCollection;  
import org.hibernate.proxy.HibernateProxy;  
import org.springframework.aop.framework.ProxyFactory;  
import org.springframework.util.StringUtils;  
/** 
* 用于Hibernate Object 序列化,访问延迟加载属性不会抛出LazyInitializationException,而会返回null值. 
* 使用: 
* <pre> 
* Blog proxyBlog = HibernateBeanSerializer(blog).getProxy; 
* </pre> 
* @author badqiu 
* @param <T> 
*/  
public   HibernateBeanSerializer <T> {  
  T proxy = null ;  
   /** 
   */  
   public HibernateBeanSerializer(T object,String... excludesProperties) {  
     (object  null ) {  
       this .proxy = null ;  
    }  {  
      ProxyFactory pf =  ProxyFactory;  
      pf.TargetClass(object.getClass);  
      pf.Optimize( true );  
      pf.Target(object);  
      pf.ProxyTargetClass( true );  
      pf.Opaque( true );  
      pf.ExposeProxy( true );  
      pf.PreFiltered( true );  
      HibernateBeanSerializerAdvice beanSerializerAdvice =  HibernateBeanSerializerAdvice;  
      beanSerializerAdvice.ExcludesProperties(excludesProperties);  
      pf.addAdvice(beanSerializerAdvice);  
       this .proxy = (T)pf.getProxy;  
    }  
  }  
   public T getProxy{  
       this .proxy;  
  }  
     private   HibernateBeanSerializerAdvice implements MethodInterceptor {  
     private String excludesProperties =  String[ 0 ];  
     public String getExcludesProperties {  
        excludesProperties;  
    }  
     public  void ExcludesProperties(String excludesProperties) {  
       this .excludesProperties = excludesProperties  null ?  String[ 0 ] : excludesProperties;  
    }  
     public Object invoke(MethodInvocation mi) throws Throwable {  
      String propertyName = getPropertyName(mi.getMethod.getName);  
      Class Type = mi.getMethod.getReturnType;  
       (propertyName  null ) {  
          mi.proceed;  
      }  
       (!Hibernate.isPropertyInitialized(mi.getThis, propertyName)) {  
           null ;  
      }  
       (isExclude(mi, propertyName)) {  
           null ;  
      }  
      Object Value = mi.proceed;  
        processReturnValue(Type, Value);  
    }  
     private Object processReturnValue(Class Type, Object Value) {  
       (Value  null )  
           null ;  
       (Type != null && Modier.isFinal(Type.getModiers)) {  
          Value;  
      }  
       //This might be a lazy-collection so we need to double check  
       (!Hibernate.isInitialized(Value)) {  
           null ;          
      }  
       //this is Hibernate Object  
       (Value instanceof HibernateProxy) {  
            HibernateBeanSerializer(Value).getProxy;  
      }   (Value instanceof PersistentCollection) {  
         (Type.isAssignableFrom(Map. )) {  
          Map proxyMap =  LinkedHashMap;  
          Map map = (Map)Value;  
          Set<Map.Entry> entrySet = map.entrySet;  
           for (Map.Entry entry : entrySet) {  
            proxyMap.put(entry.getKey,  HibernateBeanSerializer(entry.getValue));  
          }  
            proxyMap;  
        }  
        Collection proxyCollection = null ;  
         (Type.isAssignableFrom(Set. )) {  
          proxyCollection =  LinkedHashSet;  
        }   (Type.isAssignableFrom(List. )) {  
          proxyCollection =  ArrayList;  
        }  {  
            Value;  
        }  
         for (Object o : (Collection)Value) {  
          proxyCollection.add(  HibernateBeanSerializer(o).getProxy);  
        }  
          proxyCollection;  
      }  {  
          Value;  
      }  
    }  
     private  boolean isExclude(MethodInvocation mi, String propertyName)  
         throws Throwable {  
       for (String excludePropertyName : excludesProperties) {  
         (propertyName.equals(excludePropertyName)) {  
             true ;  
        }  
      }  
         false ;  
    }  
     private   String getPropertyName(String methodName) {  
      String propertyName = null ;  
       (methodName.startsWith( "get" )) {  
        propertyName = methodName.sub( "get" .length);  
      }   (methodName.startsWith( "is" )) {  
        propertyName = methodName.sub( "is" .length);  
      }   (methodName.startsWith( "" )) {  
        propertyName = methodName.sub( "" .length);  
      }  
        propertyName  null ? null : StringUtils.uncapitalize(propertyName);  
    }  
  }  
} 
package cn.org.rapid_framework.util;
import java.lang.reflect.Modier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.aopalliance.ercept.MethodInterceptor;
import org.aopalliance.ercept.MethodInvocation;
import org.hibernate.Hibernate;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.proxy.HibernateProxy;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.util.StringUtils;
/**
* 用于Hibernate Object 序列化,访问延迟加载属性不会抛出LazyInitializationException,而会返回null值.
* 使用:
* <pre>
* Blog proxyBlog = HibernateBeanSerializer(blog).getProxy;
* </pre>
* @author badqiu
* @param <T>
*/
public HibernateBeanSerializer <T> {
T proxy = null;
/**
 */
public HibernateBeanSerializer(T object,String... excludesProperties) {
 (object null) {
 this.proxy = null;
 } {
 ProxyFactory pf = ProxyFactory;
 pf.TargetClass(object.getClass);
 pf.Optimize(true);
 pf.Target(object);
 pf.ProxyTargetClass(true);
 pf.Opaque(true);
 pf.ExposeProxy(true);
 pf.PreFiltered(true);
 HibernateBeanSerializerAdvice beanSerializerAdvice = HibernateBeanSerializerAdvice;
 beanSerializerAdvice.ExcludesProperties(excludesProperties);
 pf.addAdvice(beanSerializerAdvice);
 this.proxy = (T)pf.getProxy;
 }
}
public T getProxy{
  this.proxy;
}
private HibernateBeanSerializerAdvice implements MethodInterceptor {
 private String excludesProperties = String[0];
 public String getExcludesProperties {
  excludesProperties;
 }
 public void ExcludesProperties(String excludesProperties) {
 this.excludesProperties = excludesProperties null ? String[0] : excludesProperties;
 }
 public Object invoke(MethodInvocation mi) throws Throwable {
 String propertyName = getPropertyName(mi.getMethod.getName);
 Class Type = mi.getMethod.getReturnType;
 (propertyName null) {
   mi.proceed;
 }
 (!Hibernate.isPropertyInitialized(mi.getThis, propertyName)) {
   null;
 }
 (isExclude(mi, propertyName)) {
   null;
 }
 Object Value = mi.proceed;
  processReturnValue(Type, Value);
 }
 private Object processReturnValue(Class Type, Object Value) {
 (Value null)
   null;
 (Modier.isFinal(Type.getModiers)) {
   Value;
 }
 //This might be a lazy-collection so we need to double check
 (!Hibernate.isInitialized(Value)) {
   null;  
 }
 //this is Hibernate Object
 (Value instanceof HibernateProxy) {
   HibernateBeanSerializer(Value).getProxy;
 } (Value instanceof PersistentCollection) {
  (Type.isAssignableFrom(Map.)) {
  Map proxyMap = LinkedHashMap;
  Map map = (Map)Value;
  Set<Map.Entry> entrySet = map.entrySet;
  for(Map.Entry entry : entrySet) {
   proxyMap.put(entry.getKey, HibernateBeanSerializer(entry.getValue));
  }
   proxyMap;
  }
  Collection proxyCollection = null;
  (Type.isAssignableFrom(Set.)) {
  proxyCollection = LinkedHashSet;
  } (Type.isAssignableFrom(List.)) {
  proxyCollection = ArrayList;
  } {
   Value;
  }
  for(Object o : (Collection)Value) {
  proxyCollection.add( HibernateBeanSerializer(o).getProxy);
  }
   proxyCollection;
 } {
   Value;
 }
 }
 private boolean isExclude(MethodInvocation mi, String propertyName)
  throws Throwable {
 for(String excludePropertyName : excludesProperties) {
  (propertyName.equals(excludePropertyName)) {
   true;
  }
 }
  false;
 }
 private String getPropertyName(String methodName) {
 String propertyName = null;
 (methodName.startsWith("get")) {
  propertyName = methodName.sub("get".length);
 } (methodName.startsWith("is")) {
  propertyName = methodName.sub("is".length);
 } (methodName.startsWith("")) {
  propertyName = methodName.sub("".length);
 }
  propertyName null ? null : StringUtils.uncapitalize(propertyName);
 }
}
}


Tags:  序列化 spring延迟加载 延迟加载 hibernate延迟加载

延伸阅读

最新评论

发表评论