1
1
package com .fasterxml .jackson .datatype .hibernate5 ;
2
2
3
+ import java .beans .Introspector ;
3
4
import java .io .IOException ;
5
+ import java .lang .reflect .Field ;
6
+ import java .lang .reflect .Method ;
4
7
import java .util .HashMap ;
5
8
6
9
import com .fasterxml .jackson .core .JsonGenerator ;
18
21
import org .hibernate .engine .spi .SessionImplementor ;
19
22
import org .hibernate .proxy .HibernateProxy ;
20
23
import org .hibernate .proxy .LazyInitializer ;
24
+ import org .hibernate .proxy .pojo .BasicLazyInitializer ;
21
25
22
26
/**
23
27
* Serializer to use for values proxied using {@link org.hibernate.proxy.HibernateProxy}.
@@ -174,15 +178,18 @@ protected Object findProxied(HibernateProxy proxy)
174
178
LazyInitializer init = proxy .getHibernateLazyInitializer ();
175
179
if (!_forceLazyLoading && init .isUninitialized ()) {
176
180
if (_serializeIdentifier ) {
177
- final String idName ;
181
+ String idName ;
178
182
if (_mapping != null ) {
179
183
idName = _mapping .getIdentifierPropertyName (init .getEntityName ());
180
184
} else {
181
185
final SessionImplementor session = init .getSession ();
182
186
if (session != null ) {
183
187
idName = session .getFactory ().getIdentifierPropertyName (init .getEntityName ());
184
188
} else {
185
- idName = init .getEntityName ();
189
+ idName = ProxyReader .getIdentifierPropertyName (init );
190
+ if (idName == null ) {
191
+ idName = init .getEntityName ();
192
+ }
186
193
}
187
194
}
188
195
final Object idValue = init .getIdentifier ();
@@ -194,4 +201,45 @@ protected Object findProxied(HibernateProxy proxy)
194
201
}
195
202
return init .getImplementation ();
196
203
}
204
+
205
+ /**
206
+ * Inspects a Hibernate proxy to try and determine the name of the identifier property
207
+ * (Hibernate proxies know the getter of the identifier property because it receives special
208
+ * treatment in the invocation handler). Alas, the field storing the method reference is
209
+ * private and has no getter, so we must resort to ugly reflection hacks to read its value ...
210
+ */
211
+ protected static class ProxyReader {
212
+
213
+ // static final so the JVM can inline the lookup
214
+ private static final Field getIdentifierMethodField ;
215
+
216
+ static {
217
+ try {
218
+ getIdentifierMethodField = BasicLazyInitializer .class .getDeclaredField ("getIdentifierMethod" );
219
+ getIdentifierMethodField .setAccessible (true );
220
+ } catch (Exception e ) {
221
+ // should never happen: the field exists in all versions of hibernate 4 and 5
222
+ throw new RuntimeException (e );
223
+ }
224
+ }
225
+
226
+ /**
227
+ * @return the name of the identifier property, or null if the name could not be determined
228
+ */
229
+ static String getIdentifierPropertyName (LazyInitializer init ) {
230
+ try {
231
+ Method idGetter = (Method ) getIdentifierMethodField .get (init );
232
+ if (idGetter == null ) {
233
+ return null ;
234
+ }
235
+ String name = idGetter .getName ();
236
+ if (name .startsWith ("get" )) {
237
+ name = Introspector .decapitalize (name .substring (3 ));
238
+ }
239
+ return name ;
240
+ } catch (IllegalAccessException e ) {
241
+ throw new RuntimeException (e );
242
+ }
243
+ }
244
+ }
197
245
}
0 commit comments