HHH-12982 - Generify Hibernate#unproxy

This commit is contained in:
Vlad Mihalcea 2018-09-19 10:26:16 +03:00
parent 340618c9a0
commit 01bf67e4b8
2 changed files with 195 additions and 122 deletions

View File

@ -212,4 +212,16 @@ public final class Hibernate {
return proxy;
}
}
/**
* Unproxies a {@link HibernateProxy}. If the proxy is uninitialized, it automatically triggers an initialization.
* In case the supplied object is null or not a proxy, the object will be returned as-is.
*
* @param proxy the {@link HibernateProxy} to be unproxied
* @param entityClass the entity type
* @return the proxy's underlying implementation object, or the supplied object otherwise
*/
public static <T> T unproxy(T proxy, Class<T> entityClass) {
return entityClass.cast( unproxy( proxy ) );
}
}

View File

@ -6,152 +6,213 @@
*/
package org.hibernate.test.proxy;
import java.util.Objects;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import org.hibernate.Hibernate;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.jboss.logging.Logger;
import org.junit.Test;
import javax.persistence.*;
import java.util.Objects;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
public class HibernateUnproxyTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{Parent.class, Child.class};
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Parent.class, Child.class };
}
@Test
public void testInitializedProxyCanBeUnproxied() {
Parent p = new Parent();
Child c = new Child();
p.setChild(c);
doInJPA(this::entityManagerFactory, (entityManager -> {
entityManager.persist(p);
}));
doInJPA(this::entityManagerFactory, (entityManager -> {
Parent parent = entityManager.find(Parent.class, p.getId());
Child child = parent.getChild();
assertFalse(Hibernate.isInitialized(child));
Hibernate.initialize(child);
Child unproxiedChild = (Child) Hibernate.unproxy(child);
assertEquals(Child.class, unproxiedChild.getClass());
}));
}
@Test
public void testInitializedProxyCanBeUnproxied() {
Parent p = new Parent();
Child c = new Child();
p.setChild( c );
@Test
public void testNotInitializedProxyCanBeUnproxiedWithInitialization() {
Parent p = new Parent();
Child c = new Child();
p.setChild(c);
doInJPA(this::entityManagerFactory, (entityManager -> {
entityManager.persist(p);
}));
doInJPA(this::entityManagerFactory, (entityManager -> {
Parent parent = entityManager.find(Parent.class, p.getId());
Child child = parent.getChild();
assertFalse(Hibernate.isInitialized(child));
Child unproxiedChild = (Child) Hibernate.unproxy(child);
assertTrue(Hibernate.isInitialized(child));
assertEquals(Child.class, unproxiedChild.getClass());
}));
}
doInJPA( this::entityManagerFactory, ( entityManager -> {
entityManager.persist( p );
} ) );
@Test
public void testNotHibernateProxyShouldThrowException() {
Parent p = new Parent();
Child c = new Child();
p.setChild(c);
doInJPA(this::entityManagerFactory, (entityManager -> {
entityManager.persist(p);
}));
doInJPA(this::entityManagerFactory, (entityManager -> {
Parent parent = entityManager.find(Parent.class, p.getId());
assertSame(parent, Hibernate.unproxy(parent));
}));
}
doInJPA( this::entityManagerFactory, ( entityManager -> {
Parent parent = entityManager.find( Parent.class, p.getId() );
Child child = parent.getChild();
@Test
public void testNullUnproxyReturnsNull() {
assertNull(Hibernate.unproxy(null));
}
assertFalse( Hibernate.isInitialized( child ) );
Hibernate.initialize( child );
@Test
public void testProxyEquality() {
Parent parent = doInJPA(this::entityManagerFactory, (entityManager -> {
Parent p = new Parent();
p.name = "John Doe";
entityManager.persist(p);
return p;
}));
doInJPA(this::entityManagerFactory, (entityManager -> {
Parent p = entityManager.getReference(Parent.class, parent.getId());
assertFalse(parent.equals(p));
assertTrue(parent.equals(Hibernate.unproxy(p)));
}));
}
Child unproxiedChild = (Child) Hibernate.unproxy( child );
assertEquals( Child.class, unproxiedChild.getClass() );
} ) );
@Entity(name = "Parent")
public static class Parent {
@Id
@GeneratedValue
private Integer id;
doInJPA( this::entityManagerFactory, ( entityManager -> {
Parent parent = entityManager.find( Parent.class, p.getId() );
Child child = parent.getChild();
private String name;
assertFalse( Hibernate.isInitialized( child ) );
Hibernate.initialize( child );
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Child child;
Child unproxiedChild = Hibernate.unproxy( child, Child.class );
public Integer getId() {
return id;
}
assertEquals( Child.class, unproxiedChild.getClass() );
} ) );
}
public void setChild(Child child) {
this.child = child;
child.setParent(this);
}
@Test
public void testNotInitializedProxyCanBeUnproxiedWithInitialization() {
Parent p = new Parent();
Child c = new Child();
p.setChild( c );
public Child getChild() {
return child;
}
doInJPA( this::entityManagerFactory, ( entityManager -> {
entityManager.persist( p );
} ) );
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Parent parent = (Parent) o;
return Objects.equals(name, parent.name);
}
doInJPA( this::entityManagerFactory, ( entityManager -> {
Parent parent = entityManager.find( Parent.class, p.getId() );
Child child = parent.getChild();
@Override
public int hashCode() {
return Objects.hash(name);
}
}
assertFalse( Hibernate.isInitialized( child ) );
@Entity(name = "Child")
public static class Child {
@Id
@GeneratedValue
private Integer id;
Child unproxiedChild = (Child) Hibernate.unproxy( child );
@OneToOne(fetch = FetchType.LAZY)
private Parent parent;
assertTrue( Hibernate.isInitialized( child ) );
assertEquals( Child.class, unproxiedChild.getClass() );
} ) );
public Integer getId() {
return id;
}
doInJPA( this::entityManagerFactory, ( entityManager -> {
Parent parent = entityManager.find( Parent.class, p.getId() );
Child child = parent.getChild();
public void setParent(Parent parent) {
this.parent = parent;
}
assertFalse( Hibernate.isInitialized( child ) );
public Parent getParent() {
return parent;
}
}
Child unproxiedChild = Hibernate.unproxy( child, Child.class );
assertTrue( Hibernate.isInitialized( child ) );
assertEquals( Child.class, unproxiedChild.getClass() );
} ) );
}
@Test
public void testNotHibernateProxyShouldThrowException() {
Parent p = new Parent();
Child c = new Child();
p.setChild( c );
doInJPA( this::entityManagerFactory, ( entityManager -> {
entityManager.persist( p );
} ) );
doInJPA( this::entityManagerFactory, ( entityManager -> {
Parent parent = entityManager.find( Parent.class, p.getId() );
assertSame( parent, Hibernate.unproxy( parent ) );
} ) );
doInJPA( this::entityManagerFactory, ( entityManager -> {
Parent parent = entityManager.find( Parent.class, p.getId() );
assertSame( parent, Hibernate.unproxy( parent, Parent.class ) );
} ) );
}
@Test
public void testNullUnproxyReturnsNull() {
assertNull( Hibernate.unproxy( null ) );
assertNull( Hibernate.unproxy( null, Parent.class ) );
}
@Test
public void testProxyEquality() {
Parent parent = doInJPA( this::entityManagerFactory, ( entityManager -> {
Parent p = new Parent();
p.name = "John Doe";
entityManager.persist( p );
return p;
} ) );
doInJPA( this::entityManagerFactory, ( entityManager -> {
Parent p = entityManager.getReference( Parent.class, parent.getId() );
assertFalse( parent.equals( p ) );
assertTrue( parent.equals( Hibernate.unproxy( p ) ) );
} ) );
doInJPA( this::entityManagerFactory, ( entityManager -> {
Parent p = entityManager.getReference( Parent.class, parent.getId() );
assertFalse( parent.equals( p ) );
assertTrue( parent.equals( Hibernate.unproxy( p, Parent.class ) ) );
} ) );
}
@Entity(name = "Parent")
public static class Parent {
@Id
@GeneratedValue
private Integer id;
private String name;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Child child;
public Integer getId() {
return id;
}
public void setChild(Child child) {
this.child = child;
child.setParent( this );
}
public Child getChild() {
return child;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
Parent parent = (Parent) o;
return Objects.equals( name, parent.name );
}
@Override
public int hashCode() {
return Objects.hash( name );
}
}
@Entity(name = "Child")
public static class Child {
@Id
@GeneratedValue
private Integer id;
@OneToOne(fetch = FetchType.LAZY)
private Parent parent;
public Integer getId() {
return id;
}
public void setParent(Parent parent) {
this.parent = parent;
}
public Parent getParent() {
return parent;
}
}
}