Hi team,
In our application we use these properties for the persistent unit:
<property name="hibernate.default_batch_fetch_size" value="100"/>
<property name="hibernate.jdbc.batch_size" value="100"/>
<property name="hibernate.jdbc.fetch_size" value="400"/>
When we were on the Hibernate 5.4.x version, the above properties only changed the “global” BatchSize but since Hibernate 6.2 the effective fetch type was changed to LAZY for @ManyToOne relations.
Digging into Hibernate modules shows that setting “global” BatchSize forces to use BatchInitializeEntitySelectFetchInitializer instead of the default EntitySelectFetchInitialize for @ManyToOne fields
Then in the BatchInitializeEntitySelectFetchInitializer#resolveInstance() method, we have got a new logic that forces to use a Proxy. As a result for our EAGER @ManyToOne field, we got the HibernateProxy.
(in Hibernate 6.6 that code was changed a bit but core logic remains the same)
// Force creating a proxy
initializedEntityInstance = rowProcessingState.getSession().internalLoad(
entityKey.getEntityName(),
entityKey.getIdentifier(),
false,
false
);
Besides the changes in the above LAZY/EAGER behavior, we have another unexpected side effect related to our Entity customization.
In our Framework we have such entity:
@Entity
public class OrdeImpl {
@ManyToOne(targetEntity = CustomerImpl.class)
@JoinColumn(name = "CUSTOMER_ID")
protected Customer customer;
public Customer getCustomer() {
return this.customer;
}
}
And in our application, the Entity Customer was extended to CustomCustumer
Let’s compare 5.x and 6.x Hibernate behavior.
When we fetch Order in orderDao and then call getCustomer()
5.x
We get the extended type of that field - CustomCustumer.
This is exactly what we expected.
6.x
We get the parent Framework type of that field - Customer.
It is an instance of HibernateProxy.
Both are unexpected for us.
And then after getting that Customer from Order we could not cast it to our extended CustomCustumer -
We faced ClassCastException.
My questions are:
-
I have not found anything about changes in the default LAZY/EAGER behavior in the migration guides. Are these changes intentional?
-
Is there some way to come back to the previous behavior - always to have effective fetch type EAGER for @ManyToOne even when we use “global” BatchSize?
Thank you!