Solve Hibernate's lazy loading during hessian serialization in dubbo, and solutions for Set, Map, List collections

First, the problem:
Hibernate's lazy loading will throw Hibernate's LazyInitializationException during serialization.
Also, hibernate's Map, List, etc. will be converted into PersistentCollection objects. Generally, the serialization framework does not have a serialization scheme for this type.

Second, the main application scenarios
1. When the hibernate object is cached, the serialization operation is performed.
2. The hibernate object is serialized when using the hessian RPC operation.
3. When the hibernate object is converting the json object.

Third, the solution of one class
Use DTO/VO objects to convert hibernate objects, but the disadvantages are also obvious, the code redundancy is very large, and the DTO/VO objects are flooded.

3. Phenomenon and solutions for Class
2 1. Solution for scenario 1 (cache of hibernate objects)
1) Change the objects that need to be loaded lazily to non-lazy loading. This is actually quite normal. Since you need to cache objects, why delay loading? So this plan is understandable.

2. The solution for scenario 2 (serialization of RPC)
The biggest difference between RPC serialization and conversion to json is that this serialization does not call the get method to obtain the value, it is an IO operation, so the 3 solution cannot be used. use.

I encountered a problem when serializing with hessian in dubbo, so let's talk about this framework.
In fact, it has been described in the above question, that is, the PersistentCollection object cannot be recognized, so add a method for serialization.

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);
            }
        }

    }
}


By adding configuration files in dubbo, you can add your own serialization factory.






3. For the phenomenon and scheme of scenario 3 (hibernate performs json object conversion)
1) Hibernate throws LazyInitializationException if the session is closed when the lazy-loaded property access is encountered
2) The one-to-many and other associations in Hibernate are in the sequence If there is no control during serialization, the entire database may be serialized.
3) Excessive use of DTO/ValueObject to solve this problem.

Solution:

1. You can use Alibaba's fastjson to achieve controllable serialization of this one-to-many or many-to-one object by adding DisableCircularReferenceDetect in SerializerFeature during serialization. As for lazy loading, OpenSessionInView can be used, which is only limited to the web.

2. Generate a dynamic proxy for the Entity object, intercept the getXXXX() method, and return null instead of throwing LazyInitializationException if the lazy-loaded property is accessed, recursively generate a proxy for the property, as long as the property that is not lazy-loaded is encountered, And the serialization will stop automatically. Avoid the serialization of the entire Entity spread, resulting in problems that may serialize the entire database.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326683537&siteId=291194637