Skip to content

Commit d1dc914

Browse files
galovicsVlad Mihalcea
authored andcommitted
HHH-10831 - Hibernate method to unproxy a HibernateProxy
1 parent 28d7d19 commit d1dc914

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

hibernate-core/src/main/java/org/hibernate/Hibernate.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,20 @@ public static boolean isPropertyInitialized(Object proxy, String propertyName) {
195195
return true;
196196
}
197197

198+
/**
199+
* Unproxies a {@link HibernateProxy}. If the proxy is uninitialized, it automatically triggers an initialization.
200+
* In case the supplied object is null or not a proxy, the object will be returned as-is.
201+
*
202+
* @param proxy the {@link HibernateProxy} to be unproxied
203+
* @return the proxy's underlying implementation object, or the supplied object otherwise
204+
*/
205+
public static Object unproxy(Object proxy) {
206+
if (proxy instanceof HibernateProxy) {
207+
HibernateProxy hibernateProxy = (HibernateProxy) proxy;
208+
LazyInitializer initializer = hibernateProxy.getHibernateLazyInitializer();
209+
return initializer.getImplementation();
210+
} else {
211+
return proxy;
212+
}
213+
}
198214
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.test.proxy;
8+
9+
import org.hibernate.Hibernate;
10+
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
11+
import org.jboss.logging.Logger;
12+
import org.junit.Test;
13+
14+
import javax.persistence.*;
15+
16+
import java.util.Objects;
17+
18+
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
19+
import static org.junit.Assert.*;
20+
21+
public class HibernateUnproxyTest extends BaseEntityManagerFunctionalTestCase {
22+
23+
private static final Logger log = Logger.getLogger( HibernateUnproxyTest.class );
24+
25+
@Override
26+
protected Class<?>[] getAnnotatedClasses() {
27+
return new Class<?>[]{Parent.class, Child.class};
28+
}
29+
30+
@Test
31+
public void testInitializedProxyCanBeUnproxied() {
32+
Parent p = new Parent();
33+
Child c = new Child();
34+
p.setChild(c);
35+
doInJPA(this::entityManagerFactory, (entityManager -> {
36+
entityManager.persist(p);
37+
}));
38+
doInJPA(this::entityManagerFactory, (entityManager -> {
39+
Parent parent = entityManager.find(Parent.class, p.getId());
40+
Child child = parent.getChild();
41+
assertFalse(Hibernate.isInitialized(child));
42+
Hibernate.initialize(child);
43+
Child unproxiedChild = (Child) Hibernate.unproxy(child);
44+
assertEquals(Child.class, unproxiedChild.getClass());
45+
}));
46+
}
47+
48+
@Test
49+
public void testNotInitializedProxyCanBeUnproxiedWithInitialization() {
50+
Parent p = new Parent();
51+
Child c = new Child();
52+
p.setChild(c);
53+
doInJPA(this::entityManagerFactory, (entityManager -> {
54+
entityManager.persist(p);
55+
}));
56+
doInJPA(this::entityManagerFactory, (entityManager -> {
57+
Parent parent = entityManager.find(Parent.class, p.getId());
58+
Child child = parent.getChild();
59+
assertFalse(Hibernate.isInitialized(child));
60+
Child unproxiedChild = (Child) Hibernate.unproxy(child);
61+
assertTrue(Hibernate.isInitialized(child));
62+
assertEquals(Child.class, unproxiedChild.getClass());
63+
}));
64+
}
65+
66+
@Test
67+
public void testNotHibernateProxyShouldThrowException() {
68+
Parent p = new Parent();
69+
Child c = new Child();
70+
p.setChild(c);
71+
doInJPA(this::entityManagerFactory, (entityManager -> {
72+
entityManager.persist(p);
73+
}));
74+
doInJPA(this::entityManagerFactory, (entityManager -> {
75+
Parent parent = entityManager.find(Parent.class, p.getId());
76+
assertSame(parent, Hibernate.unproxy(parent));
77+
}));
78+
}
79+
80+
@Test
81+
public void testNullUnproxyReturnsNull() {
82+
assertNull(Hibernate.unproxy(null));
83+
}
84+
85+
@Test
86+
public void testProxyEquality() {
87+
Parent parent = doInJPA(this::entityManagerFactory, (entityManager -> {
88+
Parent p = new Parent();
89+
p.name = "John Doe";
90+
entityManager.persist(p);
91+
return p;
92+
}));
93+
doInJPA(this::entityManagerFactory, (entityManager -> {
94+
Parent p = entityManager.getReference(Parent.class, parent.getId());
95+
assertFalse(parent.equals(p));
96+
assertTrue(parent.equals(Hibernate.unproxy(p)));
97+
}));
98+
}
99+
100+
@Entity
101+
public static class Parent {
102+
@Id
103+
@GeneratedValue
104+
private Integer id;
105+
106+
private String name;
107+
108+
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
109+
private Child child;
110+
111+
public Integer getId() {
112+
return id;
113+
}
114+
115+
public void setChild(Child child) {
116+
this.child = child;
117+
child.setParent(this);
118+
}
119+
120+
public Child getChild() {
121+
return child;
122+
}
123+
124+
@Override
125+
public boolean equals(Object o) {
126+
if (this == o) return true;
127+
if (o == null || getClass() != o.getClass()) return false;
128+
Parent parent = (Parent) o;
129+
return Objects.equals(name, parent.name);
130+
}
131+
132+
@Override
133+
public int hashCode() {
134+
return Objects.hash(name);
135+
}
136+
}
137+
138+
@Entity
139+
public static class Child {
140+
@Id
141+
@GeneratedValue
142+
private Integer id;
143+
144+
@OneToOne(fetch = FetchType.LAZY)
145+
private Parent parent;
146+
147+
public Integer getId() {
148+
return id;
149+
}
150+
151+
public void setParent(Parent parent) {
152+
this.parent = parent;
153+
}
154+
155+
public Parent getParent() {
156+
return parent;
157+
}
158+
}
159+
}

0 commit comments

Comments
 (0)