Batch Fetch for field having subtypes…Error: could not re-associate uninitialized transient collection
I have this problem running within a single Spring transaction.
I load objects of type PointerClass (See the “model” below), which contains two fields of type AbstractSuperClass.
At that point, 2 proxies of type AbstractSuperClass are are created.
I try to unproxy one of those AbstractSuperClass proxies like this:
Get a PointerClass field_1 by reflection
Call Hibernate.unproxy with that field value
Hibernate does a batch fetch for objects of type ConcreteClass_1 and ConcreteClass_2 (both extending AbstractSuperClass, which is also abstract).
The prefetching generates a query to preload a few objects of ConcreteClass_1 and ConcreteClass_2.
The returned object of type ConcreteClass_1 is perfectly fine. I can see that the ConcreteClass_2 object is also fine.
I have this in the context: An AbstractSuperClass object pointing to one of those ConcreteClass_2 objects.
But I merge that same AbstractSuperClass object with that relation nullified.
I can see that during the merge ConcreteClass_2.field_1 changes from initialized = true to false.
At a later stage I unproxy that ConcreteClass_2 objects, and set a reference to it without modifying it.
Actually, unproxying this object does nothing but returning the already loaded object. However, from my Eclipse IDE I can’t see the 2 collection fields from the super classes (field_1 and field_2 below). These fields should be empty sets (according to the database):
proxy of type PointerClass$HibernateProxy$?????? ->
$$_hibernate_interceptor of type ByteBuddyInterceptor
target of type ConcreteClass_2
field_1 of type Set
com.sun.jdi.InvocationException: Exception occurred in target VM occurred invoking method.
field_1 = empty HashSet
At flush time hibernate thinks that the ConcreteClass_2 object above is dirty (which is not true) and tries to load its fields. There is an exception trying to load the set declared in an upper class: field_1
org.hibernate.HibernateException: could not re-associate uninitialized transient collection
Putting a breakpoint in ProxyVisitor.reattachCollection before throwing the Exception:
throw new HibernateException( "could not re-associate uninitialized transient collection" );
I can see that the reason is:
PersistentSet.key == null && PersistentSet.role == null
I can also see that PersistetSet.session says closed == false
I could avoid the exception detaching the referenced object after the merge:
class_2_Instance = getReference(class_2_Instance);
Now I can make a reference from a PointerClass object to that class_2_Instance .
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class DomainObject extends PersistentObject
public abstract class ValueObject extends DomainObject
public abstract class AbstractSuperClass extends ValueObject
public class ConcreteClass_1 extends AbstractSuperClass
public class PointerClass extends ??? which in turn extends DomainObject Q: Why not make it extend DomainObject directly?
@OneToOne(fetch = FetchType.LAZY)
@OneToOne(fetch = FetchType.LAZY)
<property name="hibernate.default_batch_fetch_size" value="20"/>
<property name="hibernate.jdbc.fetch_size" value="20"/>
<property name="hibernate.jdbc.batch_size" value="20"/>
<property name="hibernate.jdbc.batch_versioned_data" value="true"/>