I create one-to-one relationship and I want to have methods that fetch the same entity(Distributor.class) but one does lazy fetch, other eager.
@Entity
@Table
public class Distributor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String site;
@OneToOne(
mappedBy = "distributor",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY,
optional = false
)
private Location location;
public void setLocation(Location repositoryLocation) {
if (repositoryLocation == null) {
if (this.location != null) {
this.location.setDataProvider(null);
}
}
else {
repositoryLocation.setDataProvider(this);
}
this.location = repositoryLocation;
}
// getters/setters/constructor
}
}
@Entity
@Table(name = "location")
public class Location {
@Id
private Long id;
@Column(name = "country_code")
private String countryCode;
private Double longitude;
private Double latitude;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
@JoinColumn(name = "id")
private Distributor distributor;
public Distributor getDistributor() {
return distributor;
}
public void setDistributor(Distributor distributor) {
this.distributor = distributor;
}
// other getters/setters
}
Biggest problem I encounter is that it seems that Spring Data JPA ignores FetchType and fetches all related tables eagerly(based on related threads and Spring Data JPA docs). All Spring Data Repository methods that get data using Distributor.class fetch Location eagerly in two selects, from Distributor and Location. By using @NamedEntityGraph as such:
@Entity
@Table
@NamedEntityGraph(
name = "distributor-entity-graph",
attributeNodes = {
@NamedAttributeNode("location"),
}
)
public class Distributor {
//spring data jpa methods
@EntityGraph(value = "distributor-entity-graph", type = EntityGraph.EntityGraphType.LOAD)
Optional<Distributor> findById(Long id);
I get single left outer join on Location if use such a graph and though it's a better type of eager load this is still eager load.
Everything I have found so far seems like bad workarounds.
Is there some more or less neat way of doing this or maybe is it better(in terms of performance first of all) just to not create the relationship and just fetch Location
on demand? Eager load is a smell but when I fetch single distributor I want to do just that in most of the cases, but in some cases I don't and especially if I do findAll().