0% found this document useful (0 votes)
219 views

How To Convert A Hibernate Proxy To A Real Entity Object - Baeldung

The document discusses how to convert a Hibernate proxy object to a real entity object. Hibernate uses proxy objects to enable lazy loading of associated entities. A proxy is created when an entity with a lazy fetch type is retrieved. To access fields on a subclass of a proxied entity, the proxy must first be converted to the real entity object. The document provides an example of retrieving a PaymentReceipt where the associated Payment is proxied, and how to unproxy it to access fields specific to the CreditCardPayment subclass.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
219 views

How To Convert A Hibernate Proxy To A Real Entity Object - Baeldung

The document discusses how to convert a Hibernate proxy object to a real entity object. Hibernate uses proxy objects to enable lazy loading of associated entities. A proxy is created when an entity with a lazy fetch type is retrieved. To access fields on a subclass of a proxied entity, the proxy must first be converted to the real entity object. The document provides an example of retrieving a PaymentReceipt where the associated Payment is proxied, and how to unproxy it to access fields specific to the CreditCardPayment subclass.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

10/3/2021 How to Convert a Hibernate Proxy to a Real Entity Object | Baeldung

(/)

How to Convert a Hibernate


Proxy to a Real Entity Object
Last modi ed: January 25, 2021

by baeldung (https://www.baeldung.com/author/baeldung/)

Persistence (https://www.baeldung.com/category/persistence/)
Spring (https://www.baeldung.com/category/spring/) +
Hibernate (https://www.baeldung.com/tag/hibernate/)

Get started with Spring 5 and Spring Boot 2, through the


Learn Spring course:
>> LEARN SPRING (/ls-course-start)

1. Overview
In this tutorial, we'll learn how to convert a Hibernate proxy (/hibernate-proxy-
load-method) to a real entity object. Before that, we'll understand when
Hibernate creates a proxy object. Then, we'll talk about why Hibernate proxy is
useful. And nally, we'll simulate a scenario where there's a need to un proxy
an object.
https://www.baeldung.com/hibernate-proxy-to-real-entity-object 1/9
10/3/2021 How to Convert a Hibernate Proxy to a Real Entity Object | Baeldung

2. When Does Hibernate Create a Proxy


Object?
Hibernate uses proxy objects to allow lazy loading (/hibernate-lazy-eager-
loading). To better visualize the scenario, let's look at the PaymentReceipt and
Payment entities:

@Entity
public class PaymentReceipt {
...
@OneToOne(fetch = FetchType.LAZY)
private Payment payment;
...
}

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Payment {
...
@ManyToOne(fetch = FetchType.LAZY)
protected WebUser webUser;
...
}

For instance, loading either of these entities will result in Hibernate creating a


proxy object for the associated eld with FetchType.LAZY.
To demonstrate, let's create and run an integration test:

@Test
public void givenPaymentReceipt_whenAccessingPayment_thenVerifyType() {
PaymentReceipt paymentReceipt =
entityManager.find(PaymentReceipt.class, 3L);
Assert.assertTrue(paymentReceipt.getPayment() instanceof
HibernateProxy);
}

From the test, we've loaded a PaymentReceipt and veri ed that the payment
object isn't an instance of CreditCardPayment — it's a HibernateProxy
object.
In contrast, without lazy loading, the previous test would fail as the returned
payment object would be an instance of CreditCardPayment.
https://www.baeldung.com/hibernate-proxy-to-real-entity-object 2/9
10/3/2021 How to Convert a Hibernate Proxy to a Real Entity Object | Baeldung

Additionally, it's worth mentioning that Hibernate is using bytecode


instrumentation to create a proxy object.
To verify this, we can add a breakpoint on the line of the integration test's
assertion statement and run it in debug mode. Now, let's see what the
debugger shows:

paymentReceipt = {PaymentReceipt@5042}
payment = {Payment$HibernateProxy$CZIczfae@5047}
"com.baeldung.jpa.hibernateunproxy.CreditCardPayment@2"
$$_hibernate_interceptor = {ByteBuddyInterceptor@5053}

From the debugger, we can see that Hibernate is using Byte Buddy (/byte-
buddy), which is a library for generating Java classes dynamically at run-time.

3. Why Is Hibernate Proxy Useful?

3.1. Hibernate Proxy for Lazy Loading


We've learned a bit about this earlier. To give more signi cance to it, let's try
removing the lazy loading mechanism from both PaymentReceipt and
Payment entities:

public class PaymentReceipt {


...
@OneToOne
private Payment payment;
...
}

public abstract class Payment {


...
@ManyToOne
protected WebUser webUser;
...
}

Now, let's quickly retrieve a PaymentReceipt and check the generated SQL
from the logs:

https://www.baeldung.com/hibernate-proxy-to-real-entity-object 3/9
10/3/2021 How to Convert a Hibernate Proxy to a Real Entity Object | Baeldung

select
paymentrec0_.id as id1_2_0_,
paymentrec0_.payment_id as payment_3_2_0_,
paymentrec0_.transactionNumber as transact2_2_0_,
payment1_.id as id1_1_1_,
payment1_.amount as amount2_1_1_,
payment1_.webUser_id as webuser_3_1_1_,
payment1_.cardNumber as cardnumb1_0_1_,
payment1_.clazz_ as clazz_1_,
webuser2_.id as id1_3_2_,
webuser2_.name as name2_3_2_
from
PaymentReceipt paymentrec0_
left outer join
(
select
id,
amount,
webUser_id,
cardNumber,
1 as clazz_
from
CreditCardPayment
) payment1_
on paymentrec0_.payment_id=payment1_.id
left outer join
WebUser webuser2_
on payment1_.webUser_id=webuser2_.id
where
paymentrec0_.id=?

As we can see from the logs, the query for the PaymentReceipt contains


multiple join statements.
Now, let's run it with lazy loading in place:

select
paymentrec0_.id as id1_2_0_,
paymentrec0_.payment_id as payment_3_2_0_,
paymentrec0_.transactionNumber as transact2_2_0_
from
PaymentReceipt paymentrec0_
where
paymentrec0_.id=?

Clearly, the generated SQL is simpli ed by omitting all the unnecessary join
statements.
https://www.baeldung.com/hibernate-proxy-to-real-entity-object 4/9
10/3/2021 How to Convert a Hibernate Proxy to a Real Entity Object | Baeldung

3.2. Hibernate Proxy for Writing Data


To illustrate, let's use it for creating a Payment and assigning a WebUser to it.
Without using a proxy, this would result in two SQL statements: a
SELECT statement to retrieve the WebUser and an INSERT statement
for Payment creation.
Let's create a test using the proxy:

@Test
public void
givenWebUserProxy_whenCreatingPayment_thenExecuteSingleStatement() {
entityManager.getTransaction().begin();

WebUser webUser = entityManager.getReference(WebUser.class, 1L);


Payment payment = new CreditCardPayment(new BigDecimal(100), webUser,
"CN-1234");
entityManager.persist(payment);

entityManager.getTransaction().commit();
Assert.assertTrue(webUser instanceof HibernateProxy);
}

It's worth highlighting that we're using entityManager.getReference(…) to obtain


a proxy object.
Next, let's run the test and check the logs:

insert
into
CreditCardPayment
(amount, webUser_id, cardNumber, id)
values
(?, ?, ?, ?)

Here, we can see that, when using the proxy, Hibernate only executed a
single statement: an INSERT statement for Payment creation.

4. Scenario: The Need for Unproxying

https://www.baeldung.com/hibernate-proxy-to-real-entity-object 5/9
10/3/2021 How to Convert a Hibernate Proxy to a Real Entity Object | Baeldung

Given our domain model, let's suppose we're retrieving a PaymentReceipt. As


we already know, it's associated with a Payment entity that has an inheritance
strategy of Table-per-Class (/hibernate-inheritance#table-per-class) and a
lazy fetch type.
In our case, based on the populated data, the associated Payment of
the PaymentReceipt is of type CreditCardPayment. However, since we're using
lazy loading, it would be a proxy object.
Now, let's look at the CreditCardPayment entity:

@Entity
public class CreditCardPayment extends Payment {

private String cardNumber;


...
}

Indeed, it wouldn't be possible to retrieve the cardNumber  eld from


the CreditCardPayment class without unproxying the payment object.
Regardless, let's try casting the payment object into a CreditCardPayment and
see what will happen:

@Test
public void
givenPaymentReceipt_whenCastingPaymentToConcreteClass_thenThrowClassCastEx
ception() {
PaymentReceipt paymentReceipt =
entityManager.find(PaymentReceipt.class, 3L);
assertThrows(ClassCastException.class, () -> {
CreditCardPayment creditCardPayment = (CreditCardPayment)
paymentReceipt.getPayment();
});
}

From the test, we saw the need to cast the payment object into


a CreditCardPayment. However, because the payment object is still a
Hibernate proxy object, we've encountered a ClassCastException.

5. Hibernate Proxy to Entity Object

https://www.baeldung.com/hibernate-proxy-to-real-entity-object 6/9
10/3/2021 How to Convert a Hibernate Proxy to a Real Entity Object | Baeldung

Since Hibernate 5.2.10, we can use the built-in static method for unproxying
Hibernate entities:

Hibernate.unproxy(paymentReceipt.getPayment());

Let's create a nal integration test using this approach:

@Test
public void
givenPaymentReceipt_whenPaymentIsUnproxied_thenReturnRealEntityObject() {
PaymentReceipt paymentReceipt =
entityManager.find(PaymentReceipt.class, 3L);
Assert.assertTrue(Hibernate.unproxy(paymentReceipt.getPayment())
instanceof CreditCardPayment);
}

From the test, we can see that we've successfully converted a Hibernate
proxy to a real entity object.
On the other hand, here's a solution before Hibernate 5.2.10:

HibernateProxy hibernateProxy = (HibernateProxy)


paymentReceipt.getPayment();
LazyInitializer initializer =
hibernateProxy.getHibernateLazyInitializer();
CreditCardPayment unproxiedEntity = (CreditCardPayment)
initializer.getImplementation();

6. Conclusion
In this tutorial, we've learned how to convert a Hibernate proxy to a real entity
object. In addition to that, we've discussed how the Hibernate proxy works and
why it's useful. Then, we simulated a situation where there's a need to un
proxy an object.
Lastly, we ran several integration tests to demonstrate our examples and
verify our solution.
As always, the full source code of the article is available over on GitHub
(https://github.com/eugenp/tutorials/tree/master/persistence-
modules/java-jpa-3).
https://www.baeldung.com/hibernate-proxy-to-real-entity-object 7/9
10/3/2021 How to Convert a Hibernate Proxy to a Real Entity Object | Baeldung

Get started with Spring 5 and Spring Boot 2, through


the Learn Spring course:
>> THE COURSE (/ls-course-end)

Comments are closed on this article!

CATEGORIES
SPRING (HTTPS://WWW.BAELDUNG.COM/CATEGORY/SPRING/)
REST (HTTPS://WWW.BAELDUNG.COM/CATEGORY/REST/)
JAVA (HTTPS://WWW.BAELDUNG.COM/CATEGORY/JAVA/)
SECURITY (HTTPS://WWW.BAELDUNG.COM/CATEGORY/SECURITY-2/)
PERSISTENCE (HTTPS://WWW.BAELDUNG.COM/CATEGORY/PERSISTENCE/)
JACKSON (HTTPS://WWW.BAELDUNG.COM/CATEGORY/JSON/JACKSON/)
HTTP CLIENT-SIDE (HTTPS://WWW.BAELDUNG.COM/CATEGORY/HTTP/)

SERIES
JAVA “BACK TO BASICS” TUTORIAL (/JAVA-TUTORIAL)
JACKSON JSON TUTORIAL (/JACKSON)
HTTPCLIENT 4 TUTORIAL (/HTTPCLIENT-GUIDE)
REST WITH SPRING TUTORIAL (/REST-WITH-SPRING-SERIES)
SPRING PERSISTENCE TUTORIAL (/PERSISTENCE-WITH-SPRING-SERIES)
SECURITY WITH SPRING (/SECURITY-SPRING)

ABOUT
ABOUT BAELDUNG (/ABOUT)

https://www.baeldung.com/hibernate-proxy-to-real-entity-object 8/9
10/3/2021 How to Convert a Hibernate Proxy to a Real Entity Object | Baeldung

THE COURSES (HTTPS://COURSES.BAELDUNG.COM)


JOBS (/TAG/ACTIVE-JOB/)
THE FULL ARCHIVE (/FULL_ARCHIVE)
WRITE FOR BAELDUNG (/CONTRIBUTION-GUIDELINES)
EDITORS (/EDITORS)
OUR PARTNERS (/PARTNERS)
ADVERTISE ON BAELDUNG (/ADVERTISE)

TERMS OF SERVICE (/TERMS-OF-SERVICE)


PRIVACY POLICY (/PRIVACY-POLICY)
COMPANY INFO (/BAELDUNG-COMPANY-INFO)
CONTACT (/CONTACT)

https://www.baeldung.com/hibernate-proxy-to-real-entity-object 9/9

You might also like