So konvertieren Sie einen Hibernate-Proxy in ein echtes Entitätsobjekt

Lesezeit: 5 Minuten

So konvertieren Sie einen Hibernate Proxy in ein echtes Entitatsobjekt
Andrej Minogin

Während eines Winterschlafs Session, ich lade einige Objekte und einige von ihnen werden aufgrund von verzögertem Laden als Proxys geladen. Es ist alles in Ordnung und ich möchte Lazy Loading nicht ausschalten.

Aber später muss ich einige der Objekte (eigentlich ein Objekt) per RPC an den GWT-Client senden. Und es kommt vor, dass dieses konkrete Objekt ein Proxy ist. Also muss ich es in ein echtes Objekt verwandeln. Ich kann in Hibernate keine Methode wie “materialisieren” finden.

Wie kann ich einige der Objekte von Proxys in Reals umwandeln, wenn ich ihre Klasse und ID kenne?

Im Moment sehe ich die einzige Lösung darin, dieses Objekt aus dem Cache von Hibernate zu entfernen und neu zu laden, aber es ist aus vielen Gründen wirklich schlecht.

So konvertieren Sie einen Hibernate Proxy in ein echtes Entitatsobjekt
Bozo

Hier ist eine Methode, die ich verwende.

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

  • Ich wollte dasselbe tun, also habe ich die Proxy-Instanz in einen ObjectOutputStream geschrieben und sie dann von einem entsprechenden ObjectInputStream zurückgelesen, und das schien zu funktionieren. Ich bin mir nicht sicher, ob es ein effizienter Ansatz ist, aber ich frage mich immer noch, warum es funktioniert hat … alle Kommentare dazu werden sehr geschätzt. Danke!

    – Shrin1000

    8. März 2011 um 11:41 Uhr


  • @ shrini1000 es hat funktioniert, weil beim Serialisieren die Sammlung initialisiert wird (wenn die Sitzung noch nicht geschlossen ist). Ebenfalls HibernateProxy definiert a writeReplace Methode, um Implementierer zu zwingen, während der Serialisierung etwas Besonderes zu tun.

    – Bozo

    8. März 2011 um 11:46 Uhr

  • Gibt es eine portable (JPA) Möglichkeit, dies zu tun?

    – Kawu

    7. Januar 2012 um 15:19 Uhr

  • Warum wirft Hibernate.initialize lazyInitializeException, wenn ich es aufrufe? Im nur mit wie: Object o = session.get(MyClass.class, id); Objekt other = o.getSomeOtherClass(); initializeAndUnproxy (andere);

    – fredcrs

    31. Januar 2012 um 10:26 Uhr

  • Sie können dasselbe ohne Ihre eigene util-Klasse tun – (T)Hibernate.unproxy(entity)

    – Panser

    30. Juni 2017 um 8:34 Uhr

1645907830 220 So konvertieren Sie einen Hibernate Proxy in ein echtes Entitatsobjekt
Vlad Mihalcea

Seit Hibernate ORM 5.2.10du kannst es so machen:

Object unproxiedEntity = Hibernate.unproxy(proxy);

Vor dem Winterschlaf 5.2.10. Der einfachste Weg, dies zu tun, war die Verwendung von unproxy Methode, die von Hibernate intern angeboten wird PersistenceContext Implementierung:

Object unproxiedEntity = ((SessionImplementor) session)
                         .getPersistenceContext()
                         .unproxy(proxy);

  • Behandelt der Aufruf dieser Funktion bei einer übergeordneten Entität Sammlungsfelder? zB wenn Sie eine haben Department mit Liste von Studentmusst du noch unproxy(department.getStudents()) – oder reicht es einfach unproxy(department)?

    – trafalmadorianisch

    28. November 2019 um 4:01 Uhr


  • Nur der angegebene Proxy wird initialisiert. Es wird nicht an Assoziationen kaskadiert, da dies möglicherweise Tonnen von Daten laden könnte, wenn Sie zufällig eine Root-Entität entproxyn.

    – Vlad Mihalcea

    28. November 2019 um 4:15 Uhr

  • aber PersistentContext#unproxy(proxy) löst eine Ausnahme aus, wenn der Proxy währenddessen nicht initialisiert ist Hibernate.unproxy(proxy) und LazyInitializer#getImplementation(proxy) Initialisieren Sie ggf. den Proxy. Aufgrund dieses Unterschieds wurde gerade eine Ausnahme abgefangen. 😉

    – bgraves

    3. Mai 2020 um 13:25 Uhr

So konvertieren Sie einen Hibernate Proxy in ein echtes Entitatsobjekt
Sanek Shu

Versuchen zu benutzen Hibernate.getClass(obj)

  • Dies gibt die Klasse und nicht das entproxyte Objekt selbst zurück

    – Stefan Haberl

    20. Juni 2013 um 21:53 Uhr

  • Eigentlich ist diese Lösung großartig, wenn wir versuchen, die Klasse von obj für Instanzen von Vergleichen zu finden.

    – João Rebelo

    30. Oktober 2018 um 11:12 Uhr

  • Beachten Sie, dass das Javadoc besagt: “Diese Operation initialisiert einen Proxy durch Nebeneffekt.”

    – snorbi

    20. Februar um 15:11 Uhr

1645907831 42 So konvertieren Sie einen Hibernate Proxy in ein echtes Entitatsobjekt
Sergej Bondarew

Ich habe folgenden Code geschrieben, der das Objekt von Proxys bereinigt (falls sie nicht bereits initialisiert sind)

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

}

Ich verwende diese Funktion über das Ergebnis meiner RPC-Dienste (über Aspekte) und sie reinigt rekursiv alle Ergebnisobjekte von Proxys (wenn sie nicht initialisiert sind).

Der Weg, den ich mit JPA 2 empfehle:

Object unproxied  = entityManager.unwrap(SessionImplementor.class).getPersistenceContext().unproxy(proxy);

  • Wie unterscheidet sich Ihre Antwort von meiner?

    – Vlad Mihalcea

    11. Januar 2016 um 4:36 Uhr

  • Ich habe diese Lösung ausprobiert … funktioniert nicht immer, wenn Sie nicht so etwas vor den Unwrap-Befehl setzen: HibernateProxy hibernateProxy = (HibernateProxy)possibleProxyObject; Wenn (hibernateProxy.getHibernateLazyInitializer().isUninitialized()){ hibernateProxy.getHibernateLazyInitializer().initialize(); }

    – Benutzer3227576

    7. Februar 2017 um 11:12 Uhr


1645907832 596 So konvertieren Sie einen Hibernate Proxy in ein echtes Entitatsobjekt
O.Badr

Ab Hiebrnate 5.2.10 Sie können verwenden Hibernate.proxy Methode zum Konvertieren eines Proxys in Ihre echte Entität:

MyEntity myEntity = (MyEntity) Hibernate.unproxy( proxyMyEntity );

  • Wie unterscheidet sich Ihre Antwort von meiner?

    – Vlad Mihalcea

    11. Januar 2016 um 4:36 Uhr

  • Ich habe diese Lösung ausprobiert … funktioniert nicht immer, wenn Sie nicht so etwas vor den Unwrap-Befehl setzen: HibernateProxy hibernateProxy = (HibernateProxy)possibleProxyObject; Wenn (hibernateProxy.getHibernateLazyInitializer().isUninitialized()){ hibernateProxy.getHibernateLazyInitializer().initialize(); }

    – Benutzer3227576

    7. Februar 2017 um 11:12 Uhr


1645907832 335 So konvertieren Sie einen Hibernate Proxy in ein echtes Entitatsobjekt
0x6B6F77616C74

Die andere Problemumgehung besteht darin, anzurufen

Hibernate.initialize(extractedObject.getSubojbectToUnproxy());

Kurz vor dem Schließen der Sitzung.

867960cookie-checkSo konvertieren Sie einen Hibernate-Proxy in ein echtes Entitätsobjekt

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy