| I've got three classes: public class A { ... @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) @JoinColumn(name = "NONPK", referencedColumnName="NONPK") private C cValue; ... } public class B { ... @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) @JoinColumn(name = "NONPK", referencedColumnName="NONPK") private C cValue; ... } public class C { ... @Id @Column(name = "ID", unique = true, nullable = false, precision = 10) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "IDNR") @NotNull private Long id; @Column(name = "NONPK", unique = true, nullable = false, length = 10) @NotNull private String nonPk; ... } When I have a query which first loads all entities of class A, with an EntityGraph to collect the entity C in the same query, it creates the entity A without any extra queries. When I load all entities of B, again loaded with an EntityGraph to load C, then an extra query is performed. Both entities have the same entity C with the same NONPK-value. I’ve traced it to the following: When A is loaded, it also loads the entity C. Because entity C is not already loaded in the session, it will load it from the resultset. Then it constructs a EntityUniqueKey based on C and A and puts that in the persistanceContext of the session (see Loader.loadFromResultSet). Later when B is loaded, it already sees entity C loaded and does not try to load it again. For B there won’t be a EntityUniqueKey. When it is time to hydrate the relationship, it tries to search for C based on the EntityUniqueKey of C and B (see TwoPhaseLoad.doInitializeEntity and EntityType.resolve, isReferenceToPrimaryKey = false). Because the entity is only available on the key of C and A, it will not find anything, therefore it will issue a query. It can be reproduced with the provided testcase. Is it possible to generate a custom EntityUniqueKey, so both A and B will use the same key and the extra query is not issued? See https://discourse.hibernate.org/t/custom-entityuniquekey-possible/1501. |