Explain Codes LogoExplain Codes Logo

How to convert a Hibernate proxy to a real entity object

java
hibernate
proxy
entity
Alex KataevbyAlex Kataev·Feb 15, 2025
TLDR

Jumping right into the code, the simplest way to unproxy a Hibernate proxy and convert it to its root entity is by using Hibernate.unproxy():

import org.hibernate.Hibernate; // ... YourEntityClass proxyEntity = // This is where the magic proxy comes into play // Time to reveal the true identity! YourEntityClass realEntity = (YourEntityClass) Hibernate.unproxy(proxyEntity);

Be sure to keep this conversion within a Hibernate session to avoid LazyInitializationException. There you go, instant unproxying, no sidekicks necessary.

All the art of unproxying

So, the fast answer provided an instant fix. Now let's dive into a deeper understanding of what's actually happening behind the scenes.

Manually initializing the proxy

Before Hibernate.unproxy() was there to save our day, we had Hibernate.initialize(). It's the "sledgehammer" approach, initializing everything on the entity.

// Is it a bird, is it a plane? Let's see if it's a proxy if (proxyEntity != null && !Hibernate.isInitialized(proxyEntity)) { Hibernate.initialize(proxyEntity); // "I have the power!", it screams } YourEntityClass realEntity = (YourEntityClass) proxyEntity;

Handling mysterious beings

The grand illusion is that the proxy acts just like our entity. But deep inside, they could be different beings. To unmask the real IMDb star behind the proxy:

Class<?> realClass = Hibernate.getClass(proxyEntity); // Just who are you, exactly?

Working with the Entity Manager

If your hands are tied and you can't use Hibernate.unproxy(), you can head back to the time-tested EntityManager for a more performant capability to deal with proxies:

SessionImplementor sessionImplementor = entityManager.unwrap(SessionImplementor.class); YourEntityClass realEntity = (YourEntityClass) sessionImplementor.getPersistenceContext().unproxy(proxyEntity);

Taming the Persistent Collection

Persistent collections like PersistentBag or PersistentList can be tricky business. By converting the collection into a LinkedHashSet, you can enjoy your collection without duplicates or order issues:

if (proxyEntity instanceof PersistentCollection) { PersistentCollection collection = (PersistentCollection) proxyEntity; return new LinkedHashSet<>(collection); // Order in the court! }

Mastery of proxy unproxying

When it comes to proxies, there's more than meets the eye. Here we'll dig into some advanced scenarios.

Recursive Unproxying

Walking through nested proxies feels like stepping into the mirror of Erised. You need to be prepared for the recursion:

public Object unproxyDeeply(Object proxyEntity) { if (proxyEntity instanceof HibernateProxy) { // "It's proxies all the way down!", it screams return unproxyDeeply(((HibernateProxy) proxyEntity).getHibernateLazyInitializer().getImplementation()); } if (proxyEntity instanceof PersistentCollection) { // Yep, it's a group effort return new LinkedHashSet<>(((PersistentCollection) proxyEntity)); } return proxyEntity; // Just a muggle, not magical at all }

Null checks to improve efficiency

Remember to wrap your logic with null checks to avoid trying to work magic on null:

if (proxyEntity != null) { // Initialization magic here }

Bypassing eviction from cache

Eviction might sound cool, but it really means to reload the cache. Why do that when you can bypass it with unproxy(), keeping your cache intact:

// Good practice: keep your friends close and your entities in cache YourEntityClass realEntity = (YourEntityClass) Hibernate.unproxy(proxyEntity);