[BAEL-4601] How to convert a Hibernate proxy to a real entity object

* Adds Domain Models
* Adds Integration Tests
This commit is contained in:
Emmanuel Yasa 2021-01-05 01:32:23 +08:00
parent f63058acb6
commit 6daa38007c
6 changed files with 257 additions and 0 deletions

View File

@ -0,0 +1,20 @@
package com.baeldung.jpa.hibernateunproxy;
import javax.persistence.Entity;
import java.math.BigDecimal;
@Entity
public class CreditCardPayment extends Payment {
private String cardNumber;
CreditCardPayment(BigDecimal amount, WebUser webUser, String cardNumber) {
this.amount = amount;
this.webUser = webUser;
this.cardNumber = cardNumber;
}
protected CreditCardPayment() {
}
}

View File

@ -0,0 +1,47 @@
package com.baeldung.jpa.hibernateunproxy;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.ManyToOne;
import java.math.BigDecimal;
import java.util.Objects;
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Payment {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
protected WebUser webUser;
protected BigDecimal amount;
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Payment payment = (Payment) o;
return Objects.equals(id, payment.id);
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
protected Payment() {
}
}

View File

@ -0,0 +1,53 @@
package com.baeldung.jpa.hibernateunproxy;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import java.util.Objects;
import java.util.UUID;
@Entity
public class PaymentReceipt {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToOne(fetch = FetchType.LAZY)
private Payment payment;
private String transactionNumber;
PaymentReceipt(Payment payment) {
this.payment = payment;
this.transactionNumber = UUID.randomUUID().toString();
}
public Payment getPayment() {
return payment;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
PaymentReceipt that = (PaymentReceipt) o;
return Objects.equals(id, that.id);
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
protected PaymentReceipt() {
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.jpa.hibernateunproxy;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Objects;
@Entity
public class WebUser {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
WebUser(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
WebUser webUser = (WebUser) o;
return Objects.equals(id, webUser.id);
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
protected WebUser() {
}
}

View File

@ -77,4 +77,24 @@
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
</properties>
</persistence-unit>
<persistence-unit name="jpa-h2-hibernate-unproxy">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.baeldung.jpa.hibernateunproxy.Payment</class>
<class>com.baeldung.jpa.hibernateunproxy.CreditCardPayment</class>
<class>com.baeldung.jpa.hibernateunproxy.PaymentReceipt</class>
<class>com.baeldung.jpa.hibernateunproxy.WebUser</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
</properties>
</persistence-unit>
</persistence>

View File

@ -0,0 +1,75 @@
package com.baeldung.jpa.hibernateunproxy;
import org.hibernate.Hibernate;
import org.hibernate.proxy.HibernateProxy;
import org.junit.Assert;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.math.BigDecimal;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class HibernateProxyIntegrationTest {
private static EntityManager entityManager;
@BeforeAll
public static void setup() {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-h2-hibernate-unproxy");
entityManager = factory.createEntityManager();
populateH2DB();
}
@Test
public void givenPaymentReceipt_whenAccessingPayment_thenVerifyType() {
PaymentReceipt paymentReceipt = entityManager.find(PaymentReceipt.class, 3L);
Assert.assertEquals(true, paymentReceipt.getPayment() instanceof HibernateProxy);
}
@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.assertEquals(true, webUser instanceof HibernateProxy);
}
@Test
public void givenPaymentReceipt_whenCastingPaymentToConcreteClass_thenThrowClassCastException() {
PaymentReceipt paymentReceipt = entityManager.find(PaymentReceipt.class, 3L);
assertThrows(ClassCastException.class, () -> {
CreditCardPayment creditCardPayment = (CreditCardPayment) paymentReceipt.getPayment();
});
}
@Test
public void givenPaymentReceipt_whenPaymentIsUnproxied_thenReturnRealEntityObject() {
PaymentReceipt paymentReceipt = entityManager.find(PaymentReceipt.class, 3L);
Assert.assertEquals(true, Hibernate.unproxy(paymentReceipt.getPayment()) instanceof CreditCardPayment);
}
private static void populateH2DB() {
entityManager.getTransaction().begin();
WebUser webUser = new WebUser("name");
entityManager.persist(webUser);
Payment payment = new CreditCardPayment(new BigDecimal(100), webUser, "CN-1234");
entityManager.persist(payment);
PaymentReceipt receipt = new PaymentReceipt(payment);
entityManager.persist(receipt);
entityManager.getTransaction().commit();
entityManager.clear();
}
}