Little brother is a part of the programmers despise the training of dogs, yesterday to do the project encountered a problem, when the SSH framework through the Ajax interface to pass data, because the two-way association between objects caused by JSON parsing, causing memory overflow, Search the solution on the internet there is no other way besides filtering some related objects, my idea is to solve the problem of over-fetching by setting the parsing depth, and the best solution is to make a view and write a model separately. But do not want this cumbersome, and later found to change a point of view, can solve the problem of excessive analysis of the performance of the system is also very large, so do it yourself ready to write a conversion tool class, the method is also very clear recursion, reflection, using a parameter to determine the recursion depth.
Write the time also made a lot of considerations such as the object of the persistent object is actually a proxy object, how to get the value of the field, and then through the analysis of the proxy object's class name, the Hibernate proxy object is found in the class name is actually after the proxy object name plus "_" Start random string (should be random string bar), then through Clazzname.split ("_") [0] to solve the problem of the class name, and whether it is a persistent object or the original model object is applicable (of course, this is the class name does not have "_ in the case", Of course, can also be intercepted by the string to come, the diagram is convenient for me to use this method).
After solving the class name problem, thinking that I want to get all the properties of class, we first need to get the class instance of the original model and associate the Class.forName (className) used by JDBC when loading driver. So the test can be obtained by this method of class instance, the result is positive, then through reflection also solves the problem of getting the original class set, Get method, in which I consider whether the proxy object can get the same get method, because I consider the value of replication, So need to get proxy object property values, test results are also positive, and then consider the object in fact there is a two-level proxy object problem, and then think of recursion, the previous approach to solve the entity class and proxy class can get Get method, then through recursion can achieve the second resolution;
After solving the problem of the model class and the model's proxy class, we found that there might be a problem with the set proxy object, and the one-to-many in our project is used set, then I need to do a separate processing of the set, through the test found that The set proxy object is an instance of a class in hibernate, so it's good to do it, and I'll just use the Copyset method to deal with it, and copy the values from the set to a model set, and the method simply iterates through the method that calls the single object;
When I finish all the steps and find that the reflection lookup set method is problematic because the set method is a parameter, then the class that gets the parameter is my goal, think I have taken out the data from the proxy object, then I just need getclass to get his type, test OK, But then there is the problem, that is, the proxy class type problem, but this is not a problem, because it has been said, only need to do a class name processing can be resolved by Class.forName (ClassName) can be obtained;
After solving the problem of the model proxy object, it is found that the proxy object of the set needs to be processed, but since the set proxy object is a class of Hibernate, So I just want this class to let the type is set.class to solve, hql time gets out is not the ordinary date type, our model date is util.date, gets the date is the SQL packet timestamp type, but I think that since can put into the attribute, then must be inherited from the UTI L.date that's a good one. I let his type be util. Date;
After testing only need to set the recursion depth to solve the problem of over-parsing, you need to resolve a few layers on the set of several layers, universal also OK, the students only need to add a type of judgement can be processed, but also completely solve the project requirements, from the beginning to write finished total spent 3 hours, time is not long, Encountered the problem is not particularly difficult, but can through their own thinking to solve the problem is to praise himself is a man, now put the code down for everyone to discuss, what is not enough to ask you to point out;
PackageCom.gxa.bj.util;ImportJava.lang.reflect.Field;Importjava.lang.reflect.InvocationTargetException;ImportJava.lang.reflect.Method;ImportJava.sql.Timestamp;Importjava.util.ArrayList;Importjava.util.Date;ImportJava.util.HashSet;Importjava.util.List;ImportJava.util.Set;ImportOrg.hibernate.collection.internal.PersistentSet;/** * @authorkoudan125 * This class is used to resolve the excessive parsing problem when hibernate is persisted to JSON data, the parsing depth is set by layer, and the depth greater than 2 causes the inverse parsing problem * There is no better solution at present. The association is not overly complex in cases where efficiency should not be affected too much;*/ Public classConverhelper {/** * @paramLayer Parsing Depth *@paramT Parse Object *@return * @throwsClassNotFoundException *@throwsinstantiationexception *@throwsillegalaccessexception *@throwsnosuchmethodexception *@throwsSecurityException *@throwsIllegalArgumentException *@throwsInvocationTargetException * The most core method used to parse model;*/ Public StaticObject Getcopy (intlayer, Object t)throwsclassnotfoundexception, Instantiationexception, Illegalaccessexception, Nosuchmethodexception, SECURITYEXC Eption, IllegalArgumentException, invocationtargetexception {if(T = =NULL) return NULL; if(Layer > 0) {Layer--; } Else { return NULL; } Class<?> Otclass = (class<?>) T.getclass (); String Ntclassname= Otclass.getname (). Split ("_") [0];//by observing that the agent object and the entity object are related to the law is probably the "class name _ String", so that you can pass in the object to take the entity object's class name (including the incoming entity object);@SuppressWarnings ("Unchecked") Class Ntclass= Class.forName (Ntclassname);//get Entity object class instanceObject NewT = Ntclass.newinstance ();//create entity objects for storing incoming object information;field[] Fields =Ntclass.getdeclaredfields (); for(Field f:fields) {//reflection Get Object properties spell out get, set methodString FieldName =F.getname (); String Getmethodname= "Get" + fieldname.substring (0, 1). toUpperCase ()+ fieldname.substring (1); String Setmethodname= "Set" + fieldname.substring (0, 1). toUpperCase ()+ fieldname.substring (1); Method GetMethod=Otclass.getmethod (getmethodname); Object obj= Getmethod.invoke (t);//gets the value of the property in the proxy object if(obj! =NULL) {System.out.println ("Convert" +obj); System.out.println ("Convert" +Obj.getclass ()); System.out.println ("Convert" +Ntclass); String Objclassname= Obj.getclass (). GetName (). Split ("_") [0];//by observing that the agent object and the entity object are related to the law is probably the "class name _ String", so that you can pass in the object to take the entity object's class name (including the incoming entity object);Class Objclass=class.forname (objclassname);//gets the class instance of the property if(Objclass.isassignablefrom (Persistentset.class))//if the proxy object belongs to the proxy type set,hibernate is an instance of the classObjclass=set.class; Else if(Objclass.isassignablefrom (Timestamp.class))//Handling Database Fetch time issuesObjclass=date.class; Method Setmethod= Ntclass.getmethod (Setmethodname,objclass);//gets the set method in the entity class; if(objinstanceofString | | ObjinstanceofDate|| ObjinstanceofInteger) {Setmethod.invoke (NewT, obj);//if the direct set assignment is a primitive type}Else if(objinstanceofSet) {//if the Setcopy method belongs to the set callSet<object> set = (set<object>) obj; Setmethod.invoke (NewT, getsetcopy (set, layer)); } Else{//belong to other types, that is, proxy type or model type using the Getcopy method;Setmethod.invoke (NewT, getcopy (layer, obj)); } } } returnNewT; } /** * @paramSet *@paramLayer *@return * @throwsClassNotFoundException *@throwsinstantiationexception *@throwsillegalaccessexception *@throwsnosuchmethodexception *@throwsSecurityException *@throwsIllegalArgumentException *@throwsInvocationTargetException * Handles copying of set type objects;*/ Public StaticSet<object> getsetcopy (set<object> Set,intlayer)throwsclassnotfoundexception, Instantiationexception, Illegalaccessexception, Nosuchmethodexception, SECURITYEXC Eption, IllegalArgumentException, invocationtargetexception {if(Layer <= 0) { return NULL; } Layer--; Set<Object> Newset =NewHashset<>(); for(Object obj:set) {newset.add (getcopy (layer, obj)); } returnNewset; } /** * @paramlist *@paramLayer *@return * @throwsClassNotFoundException *@throwsinstantiationexception *@throwsillegalaccessexception *@throwsnosuchmethodexception *@throwsSecurityException *@throwsIllegalArgumentException *@throwsinvocationtargetexception * Processing copy list type object; * All of our projects use Query.list () so the main call to this method is to process the list*/ Public Staticlist<object> getlistcopy (List list,intlayer)throwsclassnotfoundexception, Instantiationexception, Illegalaccessexception, Nosuchmethodexception, SECURITYEXC Eption, IllegalArgumentException, invocationtargetexception {if(List = =NULL) return NULL; ArrayList<Object> arrayList =NewArraylist<>(); for(Object obj:list) {arraylist.add (getcopy (layer, obj)); } returnarrayList; }}
About SSH Persistent object to JSON bidirectional Association resolution over-the-way