Support (bytecode) lazy attributes on composites/embeddables
Description
duplicates
relates to
Activity
Former user May 25, 2018 at 11:51 PM
Depending on how https://hibernate.atlassian.net/browse/HHH-10480#icft=HHH-10480 is fixed, Hibernate may need to be changed to call BytecodeEnhancementMetadata#isAttributeLoaded
for the embeddable (not the entity) with an unqualified property name. This may cause MergeDetachedCascadedCollectionInEmbeddableTest
to fail.
Steve Ebersole August 18, 2016 at 4:30 PMEdited
I believe this needs to wait for the type system and SQL-gen changes we are working on for 6.0.
The type system, as currently designed, tries to handle the composite values the same as any other value. So, for example, you could make the entire composite/embedded on a entity lazy and it would work; however lazy within those will not work.
The other piece is the SQL generation. That could possibly re-work that to support this within 5.x, but the SQL generation code is very difficult to introduce changes to (VERY brittle) which is actually the main impetus for 6.0 - the type changes are just a pre-requisite part of that.
Andrei Ivanov August 18, 2016 at 9:08 AM
@Luis Barreiro Pretty please? 😃
Andrei Ivanov July 4, 2016 at 10:24 AM
@Luis Barreiro Any chance to get this issue fixed? 😃
Luis Barreiro March 24, 2016 at 1:30 AM
There dosn't seem to be anything wrong with the way the classes are bytecode enhanced. There is a field for the lazy interceptor on the embeddable class, and all the hooks are in place.
What seems to be going on in here is the way the entity is handled in hibernate, namely in SingleTableEntityPersister
and ComponentType
. The support for lazy properties in embedded entities seems to missing in this classes.
Right now, the defeniton of the lazyProperty*
variables in the constructor of AbstractEntityPersister
does not take into account ComponentType
. Even if it did, ComponentType
does not cary enouth information on the 'lazyness' of the attributes.
I've came up with a test case: https://github.com/barreiro/hibernate-orm/commits/HHH-10480
Initially I had an entity with a basic property marked as lazy (didn't work at first, fixed in HHH-5255).
The another entity was necessary, so I moved some common fields into an embeddable entity, but now the lazy basic property is loaded eagerly.
public class Entity { // this works @Basic(fetch = FetchType.LAZY) private String description; @Embedded private RecordData data; } @Embeddable public class RecordData { // this fails, it is loaded eagerly @Basic(fetch = FetchType.LAZY) @Lob private byte[] content; }
If you add a 2-nd field typed
RecordData
(as can be seen in my PR), an error in the bytecode enhancer is triggered:java.lang.NoClassDefFoundError: org/hibernate/test/bytecode/enhancement/lazy/basic/LazyBasicFieldAccessTestTask$Entity at org.hibernate.test.bytecode.enhancement.lazy.basic.LazyBasicFieldAccessTestTask.getAnnotatedClasses(LazyBasicFieldAccessTestTask.java:40) at org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask.prepare(AbstractEnhancerTestTask.java:30) at org.hibernate.test.bytecode.enhancement.lazy.basic.LazyBasicFieldAccessTestTask.prepare(LazyBasicFieldAccessTestTask.java:47) at org.hibernate.test.bytecode.enhancement.EnhancerTestUtils.runEnhancerTestTask(EnhancerTestUtils.java:98) at org.hibernate.test.bytecode.enhancement.EnhancerTest.testLazy(EnhancerTest.java:72) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.hibernate.testing.junit4.ExtendedFrameworkMethod.invokeExplosively(ExtendedFrameworkMethod.java:45) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74) Caused by: java.lang.ClassNotFoundException: org.hibernate.test.bytecode.enhancement.lazy.basic.LazyBasicFieldAccessTestTask$Entity not found at org.hibernate.test.bytecode.enhancement.EnhancerTestUtils$1.loadClass(EnhancerTestUtils.java:160) ... 16 more Caused by: java.lang.ClassFormatError: Duplicate interface name in class file org/hibernate/test/bytecode/enhancement/lazy/basic/LazyBasicFieldAccessTestTask$Entity at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:760) at java.lang.ClassLoader.defineClass(ClassLoader.java:642) at org.hibernate.test.bytecode.enhancement.EnhancerTestUtils$1.loadClass(EnhancerTestUtils.java:157) ... 16 more