|
If an entity has a basic column marked as lazy fetching like this:
@Basic(fetch = FetchType.LAZY) private String whatever;
And a second level cache is active for that entity
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = Constants.STATIC_CACHE)
Fetching lazy properties fails with an exception:
Caused by: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of clazz.field at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:151) at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValue(AbstractEntityTuplizer.java:716) at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValue(AbstractEntityPersister.java:4526) at org.hibernate.persister.entity.AbstractEntityPersister.initializeLazyProperty(AbstractEntityPersister.java:1341) at org.hibernate.persister.entity.AbstractEntityPersister.initializeLazyPropertiesFromCache(AbstractEntityPersister.java:1324) at org.hibernate.persister.entity.AbstractEntityPersister.initializeLazyProperty(AbstractEntityPersister.java:1230) at org.hibernate.bytecode.instrumentation.spi.AbstractFieldInterceptor.intercept(AbstractFieldInterceptor.java:95) at org.hibernate.bytecode.instrumentation.internal.javassist.FieldInterceptorImpl.readObject(FieldInterceptorImpl.java:98) at com.dreikraft.on.shopv5.pu.Onorm.$javassist_read_pfadbildResolved(Onorm.java) at com.dreikraft.on.shopv5.pu.Onorm.getPfadbildResolved(Onorm.java:115) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at javax.el.BeanELResolver.getValue(BeanELResolver.java:83) ... 95 more Caused by: java.lang.IllegalArgumentException: Can not set java.lang.String field clazz.field to org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer$1 at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150) at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63) at java.lang.reflect.Field.set(Field.java:657) at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:139)
The reason for this seems to be that AbstractEntityPersister.initializeLazyProperty there is a check whether the object is already in the cache. As it had been loaded previously, it is in the cache, but with the lazy property still not initialized.
It gets the value from the cache, but picks up a LazyPropertyInitializer$1 for the requested property. It then tries to set that value (which should be the fetched value) and fails with the exception above because the type is not valid for the property. At least needs a check in AbstractEntityPersister.initializeLazyProperty for that case to fetch the value from the datastore if the value requested is still that marker object for uninitialized properties.
As annotating a basic property as lazy is valid in JPA, this behavior is in violation of the JPA spec.
|