Per Hibernate Core docs, accessing a lazy property on a bytecode-instrumented Entity
returns an unproxied target property. From what I can tell, however, in the case where the
target property is an Entity as well, this is implemented by (in hibernate 3.3.1.GA):
-generating a proxy for target entity
-setting unwrap flag to true
-immediately unwrapping it.
In (both javassist and cglib) FieldInterceptorImpl:
public Object readObject(Object target, String name, Object oldValue) {
Object value = intercept( target, name, oldValue );
if (value instanceof HibernateProxy) {
LazyInitializer li = ( (HibernateProxy) value ).getHibernateLazyInitializer();
if ( li.isUnwrap() ) {
value = li.getImplementation();
}
}
return value;
}
In our test, The implicit call to DefaultLoadEventListener.createProxyIfNecessary()
contributes 13% of exec time, 9% coming AbstractEntityPersister.createProxy(). (our tests
execute read-only methods that hit 2nd level cache. For context, fetching actual data from
2nd level cache takes only 6% of exec time). In other words, proxy generation isn't
cheap.
Given the stated intent to return an unproxied entity why not ensure that
AbstractEntityPersister.initializeLazyProperty returns unproxied values? Better yet, why
not introduce another version of EntityType.resolveIdentifier that bypasses proxy creation
(via immediateLoad maybe)?
If there are some really good reason to create and immediately discard proxies in this
case, createProxy() should be made cheaper. 1/3 of that method is spend doing
ReflectHelper.overridesEquals(Class) in BasicLazyInitializer constructor. Any reason not
to cache results of that method (and, actually, other ReflectHelper methods)?
I'm more than happy to write contribute the code given a little guidance.
Thanks
-nikita
Show replies by date