hibernate-orm
hibernate-orm copied to clipboard
HHH-12782 Test and fix for circularity detection
This is a fix for https://hibernate.atlassian.net/browse/HHH-12782
I noticed that it will also fix https://hibernate.atlassian.net/browse/HHH-10842 and it seems like it could also fix https://hibernate.atlassian.net/browse/HHH-13085 which is why I added @gbadner
@beikov, in general, I like the approach, and I believe that it does fix HHH-13085. I like this approach better than what I did in my PR for that issue. Thanks for bringing my attention to this.
IIUC, the "other" table will usually be the table referenced by the association's foreign key. It might be a different table, if the foreign key actually references a secondary table, or a subclass table. I believe the information is there to get the correct table in all cases, but I'm not sure it's really worth it. I think what you have should work.
My biggest concern is that this fix adds extra join(s)) for lots of tests, and for at least some of them, the join adds no value.
I've only looked at a the first couple of tests that generate different SQL so far, but here are some examples where we really don't want to add an extra join.
- Eager, bidirectional one-to-one association
In org.hibernate.jpa.test.association.AssociationTest.testBidirOneToOne, when loading an Incident entity, the eager bidirectional associationm,Incident#incidentStatus / IncidentStatus#incident, only requires 1 join, because Hibernate loads IncidentStatus#incident from the session.
The "before" SQL is:
select incident0_.id as id1_0_0_, incident0_.incidentStatus_id as incident2_0_0_, incidentst1_.id as id1_1_1_ from Incident incident0_ left outer join IncidentStatus incidentst1_ on incident0_.incidentStatus_id=incidentst1_.id where incident0_.id=?
The "after" SQL is:
select incident0_.id as id1_0_0_, incident0_.incidentStatus_id as incident2_0_0_, incidentst1_.id as id1_1_1_, incident2_.id as id1_0_2_, incident2_.incidentStatus_id as incident2_0_2_ from Incident incident0_ left outer join IncidentStatus incidentst1_ on incident0_.incidentStatus_id=incidentst1_.id left outer join Incident incident2_ on incidentst1_.id=incident2_.incidentStatus_id where incident0_.id=?
The left outer join back to Incident is unnecessary.
- Initialization of a lazy bidirectional one-to-many / many-to-one association
In org.hibernate.jpa.test.callbacks.PreUpdateNewBidirectionalBagTest#testPreUpdateModifications, when a lazy collection, Person#tags, gets initialized, no joins are required, because Hibernate loads Person from the session.
The "before" SQL:
select tags0_.person_id as person_i3_1_0_, tags0_.id as id1_1_0_, tags0_.id as id1_1_1_, tags0_.description as descript2_1_1_, tags0_.person_id as person_i3_1_1_ from Tag tags0_ where tags0_.person_id=?
The "after" SQL:
select tags0_.person_id as person_i3_1_0_, tags0_.id as id1_1_0_, tags0_.id as id1_1_1_, tags0_.description as descript2_1_1_, tags0_.person_id as person_i3_1_1_, preupdaten1_.id as id1_0_2_, preupdaten1_.lastUpdatedAt as lastupda2_0_2_, preupdaten1_.name as name3_0_2_ from Tag tags0_ left outer join Person preupdaten1_ on tags0_.person_id=preupdaten1_.id where tags0_.person_id=?
The left outer join to Person is unnecessary.
I'm sure a lot of differences I'm seeing are due to these 2 cases. Could you try to refine your approach so that joins are not added in these cases? If you can do that, I can see if here are other cases where an added join is unnecessary.