The process of using ajax:hibernate Entity => json, Flex remoteobject:hibernate Entity => ActionScript object frequently encounters the following problems:
Problem:
1.Hibernate throws Lazyinitializationexception If session is closed when a deferred-load property access is encountered
In the case of One-to-many in 2.Hibernate, if there is no control in serialization, the entire database may be serialized
3. Excessive use of dto/valueobject to solve this problem.
Solution:
Generates a dynamic proxy for the entity object, blocks the Getxxxx () method, and if you are accessing a deferred-loading property, return null instead of throwing the lazyinitializationexception, recursively generating the code for the property, Serialization automatically stops whenever a property is encountered that does not delay loading. Avoid serializing the entire entity, causing problems that might serialize the entire database.
Similar solutions:
Hibernateconverter in Dwr, when serialized, a property that encounters a deferred load automatically stops the convert operation. and Hibernatebeanserializer is once and for all, regardless of object => JSON can work.
Use Use cases:
Java code
//role为原始对象
role = (Role)roleDao.getById(new Long(1));
//生成的动态代理proxyRole,访问延迟加载的属性将return null
Role proxyRole = (Role)new HibernateBeanSerializer<Role>(role).getProxy();
assertNotNull(role.getResource());
assertNull(proxyRole.getResource()); //延迟加载,为null
Hibernate.initialize(role.getResource()); //抓取进来
assertNotNull(proxyRole.getResource()); //不为null
Source.
Java code
package cn.org.rapid_framework.util;
import Java.lang.reflect.Modifier;
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.intercept.MethodInterceptor;
import org.aopalliance.intercept.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;
/**
* is used for serialization of Hibernate Object, the property that accesses the deferred load does not throw a lazyinitializationexception and returns a null value.
* Use:
* <pre>
* Blog Proxyblog = new Hibernatebeanserializer (blog). GetProxy ();
* </pre>
* @author Badqiu
* @param <T>
*/
public class Hibernatebeanserializer <T> {
T proxy = null;
/**
*/
public Hibernatebeanserializer (T object,string ... excludesproperties) {
if (object = = null) {
This.proxy = null;
}else {
Proxyfactory pf = new Proxyfactory ();
Pf.settargetclass (Object.getclass ());
Pf.setoptimize (TRUE);
Pf.settarget (object);
Pf.setproxytargetclass (TRUE);
Pf.setopaque (TRUE);
Pf.setexposeproxy (TRUE);
pf.setprefiltered (TRUE);
Hibernatebeanserializeradvice beanserializeradvice = new Hibernatebeanserializeradvice ();
beanserializeradvice.setexcludesproperties (excludesproperties);
Pf.addadvice (Beanserializeradvice);
this.proxy = (T) pf.getproxy ();
}
}
public T GetProxy () {
return this.proxy;
}
static Private class Hibernatebeanserializeradvice implements Methodinterceptor {
Private string[] excludesproperties = new String[0];
public string[] Getexcludesproperties () {
return excludesproperties;
}
public void Setexcludesproperties (string[] excludesproperties) {
this.excludesproperties = Excludesproperties = null? New string[0]: excludesproperties;
}
public Object Invoke (Methodinvocation mi) throws Throwable {
String propertyname = Getpropertyname (Mi.getmethod (). GetName ());
Class returntype = Mi.getmethod (). Getreturntype ();
if (propertyname = = null) {
return Mi.proceed ();
}
if (! Hibernate.ispropertyinitialized (Mi.getthis (), PropertyName)) {
return null;
}
if (Isexclude (MI, propertyname)) {
return null;
}
Object returnvalue = Mi.proceed ();
return Processreturnvalue (ReturnType, returnvalue);
}
private Object Processreturnvalue (Class returntype, Object returnvalue) {
if (returnvalue = null)
return null;
if (returntype!= null && modifier.isfinal (Returntype.getmodifiers ())) {
return returnvalue;
}
//this might is a lazy-collection so we need to double check
if (! Hibernate.isinitialized (returnvalue)) {
return null;
}
//this is Hibernate Object
if (returnvalue instanceof hibernateproxy) {
return to New Hibernatebeanserializer (returnvalue). GetProxy ();
}else if (returnvalue instanceof persistentcollection) {
if (Returntype.isassignablefrom (Map.class)) {
Map proxymap = new Linkedhashmap ();
map map = (map) returnvalue;
set<map.entry> entryset = Map.entryset ();
for (Map.entry entry:entryset) {
Proxymap.put (Entry.getkey (), New Hibernatebeanserializer (Entry.getvalue ()));
}
return proxymap;
}
Collection proxycollection = null;
if (Returntype.isassignablefrom (Set.class)) {
proxycollection = new Linkedhashset ();
}else if (Returntype.isassignablefrom (List.class)) {
proxycollection = new ArrayList ();
}else {
return returnvalue;
}
for (Object o: (Collection) returnvalue) {
Proxycollection.add (new Hibernatebeanserializer (O). GetProxy ());
}
return proxycollection;
}else {
return returnvalue;
}
}
Private Boolean isexclude (methodinvocation mi, String PropertyName)
throws Throwable {
for (String excludepropertyname:excludesproperties) {
if (propertyname.equals (Excludepropertyname)) {
return true;
}
}
return false;
}
private static string Getpropertyname (String methodname) {
String propertyname = null;
if (Methodname.startswith ("get")) {
propertyname = methodname.substring ("Get". Length ());
}else if (Methodname.startswith ("is")) {
PropertyName = Methodname.substring ("is". Length ());
}else if (Methodname.startswith ("set")) {
propertyname = methodname.substring ("set". Length ());
}
return propertyname = = null? Null:StringUtils.uncapitalize (PropertyName);
}
}
}
Another of these classes is part of the Rapid-framework, and the v2.0 version of Flex RemoteObject will use this approach. The preview version is about to be released