How to convert a Hibernate proxy to a real entity object

后端 未结 10 710
离开以前
离开以前 2020-11-22 16:49

During a Hibernate Session, I am loading some objects and some of them are loaded as proxies due to lazy loading. It\'s all OK and I don\'t want to turn lazy lo

相关标签:
10条回答
  • 2020-11-22 17:25

    As I explained in this article, since Hibernate ORM 5.2.10, you can do it likee this:

    Object unproxiedEntity = Hibernate.unproxy(proxy);
    

    Before Hibernate 5.2.10. the simplest way to do that was to use the unproxy method offered by Hibernate internal PersistenceContext implementation:

    Object unproxiedEntity = ((SessionImplementor) session)
                             .getPersistenceContext()
                             .unproxy(proxy);
    
    0 讨论(0)
  • 2020-11-22 17:29

    Starting from Hiebrnate 5.2.10 you can use Hibernate.proxy method to convert a proxy to your real entity:

    MyEntity myEntity = (MyEntity) Hibernate.unproxy( proxyMyEntity );
    
    0 讨论(0)
  • 2020-11-22 17:30

    The way I recommend with JPA 2 :

    Object unproxied  = entityManager.unwrap(SessionImplementor.class).getPersistenceContext().unproxy(proxy);
    
    0 讨论(0)
  • 2020-11-22 17:33

    Here's a method I'm using.

    public static <T> T initializeAndUnproxy(T entity) {
        if (entity == null) {
            throw new 
               NullPointerException("Entity passed for initialization is null");
        }
    
        Hibernate.initialize(entity);
        if (entity instanceof HibernateProxy) {
            entity = (T) ((HibernateProxy) entity).getHibernateLazyInitializer()
                    .getImplementation();
        }
        return entity;
    }
    
    0 讨论(0)
  • 2020-11-22 17:39

    Try to use Hibernate.getClass(obj)

    0 讨论(0)
  • 2020-11-22 17:40

    I've written following code which cleans object from proxies (if they are not already initialized)

    public class PersistenceUtils {
    
        private static void cleanFromProxies(Object value, List<Object> handledObjects) {
            if ((value != null) && (!isProxy(value)) && !containsTotallyEqual(handledObjects, value)) {
                handledObjects.add(value);
                if (value instanceof Iterable) {
                    for (Object item : (Iterable<?>) value) {
                        cleanFromProxies(item, handledObjects);
                    }
                } else if (value.getClass().isArray()) {
                    for (Object item : (Object[]) value) {
                        cleanFromProxies(item, handledObjects);
                    }
                }
                BeanInfo beanInfo = null;
                try {
                    beanInfo = Introspector.getBeanInfo(value.getClass());
                } catch (IntrospectionException e) {
                    // LOGGER.warn(e.getMessage(), e);
                }
                if (beanInfo != null) {
                    for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) {
                        try {
                            if ((property.getWriteMethod() != null) && (property.getReadMethod() != null)) {
                                Object fieldValue = property.getReadMethod().invoke(value);
                                if (isProxy(fieldValue)) {
                                    fieldValue = unproxyObject(fieldValue);
                                    property.getWriteMethod().invoke(value, fieldValue);
                                }
                                cleanFromProxies(fieldValue, handledObjects);
                            }
                        } catch (Exception e) {
                            // LOGGER.warn(e.getMessage(), e);
                        }
                    }
                }
            }
        }
    
        public static <T> T cleanFromProxies(T value) {
            T result = unproxyObject(value);
            cleanFromProxies(result, new ArrayList<Object>());
            return result;
        }
    
        private static boolean containsTotallyEqual(Collection<?> collection, Object value) {
            if (CollectionUtils.isEmpty(collection)) {
                return false;
            }
            for (Object object : collection) {
                if (object == value) {
                    return true;
                }
            }
            return false;
        }
    
        public static boolean isProxy(Object value) {
            if (value == null) {
                return false;
            }
            if ((value instanceof HibernateProxy) || (value instanceof PersistentCollection)) {
                return true;
            }
            return false;
        }
    
        private static Object unproxyHibernateProxy(HibernateProxy hibernateProxy) {
            Object result = hibernateProxy.writeReplace();
            if (!(result instanceof SerializableProxy)) {
                return result;
            }
            return null;
        }
    
        @SuppressWarnings("unchecked")
        private static <T> T unproxyObject(T object) {
            if (isProxy(object)) {
                if (object instanceof PersistentCollection) {
                    PersistentCollection persistentCollection = (PersistentCollection) object;
                    return (T) unproxyPersistentCollection(persistentCollection);
                } else if (object instanceof HibernateProxy) {
                    HibernateProxy hibernateProxy = (HibernateProxy) object;
                    return (T) unproxyHibernateProxy(hibernateProxy);
                } else {
                    return null;
                }
            }
            return object;
        }
    
        private static Object unproxyPersistentCollection(PersistentCollection persistentCollection) {
            if (persistentCollection instanceof PersistentSet) {
                return unproxyPersistentSet((Map<?, ?>) persistentCollection.getStoredSnapshot());
            }
            return persistentCollection.getStoredSnapshot();
        }
    
        private static <T> Set<T> unproxyPersistentSet(Map<T, ?> persistenceSet) {
            return new LinkedHashSet<T>(persistenceSet.keySet());
        }
    
    }
    

    I use this function over result of my RPC services (via aspects) and it cleans recursively all result objects from proxies (if they are not initialized).

    0 讨论(0)
提交回复
热议问题