191 votes

Conversion d’Hibernate proxy pour l’objet réel

Au cours de la session Hibernate je suis le chargement de certains objets et certains d'entre eux sont chargés de procurations dues à chargement différé. Tout est OK et je ne veux pas tourner le chargement paresseux off.

Mais plus tard, j'ai besoin d'envoyer des objets (en fait, un seul objet) à l'GWT client via RPC. Et il se trouve que cette objet concret est un proxy. J'ai donc besoin de l'activer à l'objet réel. Je ne peux pas trouver une méthode comme "matérialiser" en veille prolongée.

Comment puis-je transformer certains objets de procurations de reals, connaissant leur classe et ID?

Pour le moment la seule solution que je vois est d'expulser l'objet de mise en veille prolongée du cache et de le recharger, mais il est vraiment mauvais pour de nombreuses raisons.

Merci à l'avance!

260voto

Bozho Points 273663

Voici une méthode que j’utilise.

18voto

Sanek Shu Points 111

Essayez d’utiliser``

13voto

Sergey Bondarev Points 11

J'ai écrit le code suivant qui nettoie objet de procurations (si elles ne sont pas initialisées)

    public static <T> T cleanFromProxies(T value) {
        T result = unproxyObject(value);
        cleanFromProxies(result, new ArrayList<Object>());
        return result;
    }


    private static void cleanFromProxies(Object value, List<Object> handledObjects) {
        if ((value != null) && (!isProxy(value)) &&   !CollectionsUtils.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 boolean isProxy(Object value) {
        if (value == null) {
            return false;
        }
        if ((value instanceof HibernateProxy) || (value instanceof PersistentCollection)) {
            return true;
        }
        return false;
    }

    @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 unproxyHibernateProxy(HibernateProxy hibernateProxy) {
        Object result = hibernateProxy.writeReplace();
        if (!(result instanceof SerializableProxy)) {
            return result;
        }
        return null;
    }


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

J'utilise cette fonction sur la suite de mes services RPC (via) et il nettoie de façon récursive tous les objets de résultat à partir des procurations (si eux non initialisé). Écrivez-moi si vous avez plus de questions. J'espère que ça va vous aider.

2voto

Legna Points 141

vous pourriez trouver hibernate4gwt (Gilead depuis 2008) utile pour le problème que vous rencontrez

1voto

OndrejM Points 81

J'ai trouvé une solution pour deproxy une classe en utilisant le standard de Java et l'API JPA. Testé avec mise en veille prolongée, mais ne nécessite pas d'hiberner comme une dépendance et devrait fonctionner avec toutes les JPA fournisseurs.

Onle une exigence, il est nécessaire de modifier la classe parent (Adresse) et ajouter une simple méthode d'assistance.

Idée générale: ajout de la méthode d'assistance à la classe parent qui renvoie lui-même. lorsque la méthode est appelée sur le proxy, il transfère l'appel réel de l'instance et le rendement réel de l'instance.

La mise en œuvre est un peu plus complexe, que la mise en veille reconnaît que proxy classe renvoie lui-même et renvoie toujours proxy au lieu d'un vrai exemple. Solution de contournement consiste à envelopper retourné instance dans une simple classe wrapper, qui a différent type de classe que le réel de l'instance.

Dans le code:

class Address {
   public AddressWrapper getWrappedSelf() {
       return new EntityWrapper(this);
   }
...
}

class AddressWrapped {
    private Address wrappedAddress;
...
}

Pour lancer l'Adresse proxy de vrais sous-classe, l'utilisation suivantes:

Address address = dao.getSomeAddress(...);
Address deproxiedAddress = address.getWrappedSelf().getWrappedAddress();
if (deproxiedAddress instanceof WorkAddress) {
WorkAddress workAddress = (WorkAddress)deproxiedAddress;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X