I'm using @EntityGraph to eagerly load some attributes. However, something broke after updating from 6.1. 5. x Final to 6. x 1 . 6.Final
Suppose we have a human who can have multiple houses:
{code:java} public class Human { @Id @Column(name = "ID", nullable = false, updatable = false, precision = 20) @GeneratedValue private BigInteger id;
@EqualsAndHashCode.Exclude @ToString.Exclude @OneToMany(mappedBy = "human", cascade = CascadeType.ALL) @OnDelete(action = OnDeleteAction.CASCADE) private Collection<House> houses; } {code}
When searching for a human, by ID, EntityGraph can eagerly load some attributes:
{code:java} @EntityGraph(attributePaths = { "houses.address" }) @Query ("SELECT h FROM Human h WHERE h.id = ?1") Human findByIdEagerHouseAddresses(Integer id); {code}
This will create SQL with left (outer by default) joins:
{code:sql} select h1_0.id, h2_0.human_fk, h2_0.address_fk, a1_0.id from human h1_0 left join house h2_0 on h1_0.id = h2_0.human_fk left join address a1_0 on a1_0.id = h2_0.address_fk where h1_0.id in (?) {code}
This is acceptable because I will get the human even if they don't have a house.
However, if the address field in the house has the @Id annotation, the outer join will change to "inner":
{code:java} @Entity public class House { @Id @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "human_fk", nullable = false, updatable = false) private Human human;
@Id // THIS ANNOTATION WAS ADDED @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "address_fk", nullable = false, updatable = false) private Address address; } {code}
{code:sql} select h1_0.id, h2_0.human_fk, h2_0.address_fk, a1_0.id from human h1_0 left join house h2_0 on h1_0.id = h2_0.human_fk join address a1_0 on a1_0.id = h2_0.address_fk where h1_0.id in (?) {code}
If a human does not have a house, the query returns nothing due to the inner join, which seems like a bug.
|
|