Assume I have the following entity:
@Entity
public class Foo {
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
@ManyToOne(fetch = LAZY)
private EntityA a;
@ManyToOne(fetch = LAZY)
private EntityB b;
.
.
.
@ManyToOne(fetch = LAZY)
private EntityX x;
}
All relationships are lazy loaded because in majority of cases they're not needed for business logic. Next, assume there's an endpoint that returns all data for a specific Foo entity by ID. There're two options to retrieve data:
Rely on lazy loading which means that X database requests will be made for X relationships. This approach seems fine considering that requests are lightweight and they fetch only 1 row per table. Additionally, its more pleasant for code maintenance.
Write a big HQL query that JOIN FETCHes all necessary relationships. This approach performs only one database request and works by a few milliseconds faster than the option above, however, hibernate generates a very big SQL that might have performance issues in specific edge cases and the developer has to maintain a big HQL query.
Are there any best practices around this case? Which approach would be better for this specific scenario?
however, hibernate generates a very big SQL that might have performance issues in specific edge cases
I don't quite understand. The word "might" seems to be doing a whole lotta work here. Do you have any actual evidence that the SQL Hibernate generates results in poor performance?
Because in general, joining multiple @ManyToOne
associations is something that the database is able to do very efficiently, and is unlikely to cause a problem.
And to be clear "a very big SQL" is not in any way an indicator of poor performance.
Therefore: your option 2 is the recommendation.
Now, on the other hand, problems do arise if you join multiple @OneToMany
associations, and so for that case one might need to consider more exotic solutions, for example, the use of FetchMode.SUBSELECT
. But that is not the case you have exhibited in the code above.