I’m using @EntityGraph to load some attributes eagerly. But sth has broken after update from 5.x to 6.x.
Let say we have a human who can have multiple houses:
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;
}
When search for him, by id, EntityGraph can load something eagerly:
@EntityGraph(attributePaths = { "houses.address" })
@Query ("SELECT h FROM Human h WHERE h.id IN ?1")
Human findByIdEagerHouseAddresses(Integer id);
this will create sql with left (outer by default) joins:
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 (?)
This is ok, I will get my human, even if it has no house.
But if address field in house will have annotation @Id, outer join will change to “inner”:
@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;
}
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 (?)
If a human does not have a house, query returns nothing, because of join (which is inner), which seems like a bug.
Is it really a bug? or a feature? I have checked this on latest 3.1.1 spring boot.