Hey,
so the problems related to the type variable handling I did aren't fully
solved. There is one other case that was reported today:
https://hibernate.atlassian.net/browse/HHH-12375
I'm not sure how to handle this. Let me explain you the model and the
problem.
@Entity class BaseEntity { @Id Integer id; }
@Entity class EntityA extends BaseEntity { @ManyToOne EntityC relation; }
@Entity class EntityB extends BaseEntity { @ManyToOne EntityD relation; }
@Entity class EntityC {...}
@Entity class EntityD {...}
The essence is, that EntityA and EntityB define properties with the same
names but have unrelated types. It's actually the same problem for
collections.
Since EntityA and EntityB extend BaseEntity and because BaseEntity is an
@Entity, the Hibernate code tries to add "EntityA.relation" and
"EntityB.relation" to the PropertyMapping of BaseEntity. Before my fix,
the property which is added first won and subsequent adds are ignored.
This is presumably done to support implicit downcasting. My fix was
about making use of a common super type if possible and disallowing
ambiguous access.
The problem the user now reported is, when using FetchType.EAGER there
is an exception which states that property "relation" could not be found
on type "BaseEntity". This is because I register "null" as type to
signal that it's not really possible to use that property with that
persister(BaseEntity in this case). During booting, the load plan for
BaseEntity is built, for which the SQL is pre-generated. At this point,
the exception happens, because "null" is registered as type for the
property "relation". This will cause the property to be considered as
non-existant wrt getPropertyType. The code before my fix was essentially
broken, because it doesn't handle eager fetching properly due to the
"first property wins" strategy. A property might only be loaded through
a secondary query due to lazy loading rather than by the defined fetch
style. An implicit downcasted join using the property might lead to
non-deterministic results.
One of the reasons for doing the fix, was to prevent the possibility of
being hit by the non-determinism. I had a mapping that was using the
type variable approach and I had to find out the non-determinism the
hard way. I'd like to prevent access to such conflicting attributes from
the top level type through implicit downcasting, so IMO the only real
solution is to exclude the conflicting attributes in the load plan.
The "best" solution would be to introduce a synthetic type that
represents the union of the unrelated property types, but to me this
seems to be quite a lot of work.
I have implemented the proposed solution here:
https://github.com/hibernate/hibernate-orm/pull/2190
We need to release this fix soon as the current state is broken for the
EAGER configuration. What do you think about the solution or the matter
in general?
--
Mit freundlichen Grüßen,
------------------------------------------------------------------------
*Christian Beikov*