0

I'm wondering about what is the best ways to fetch entity relations.

Assume we have these these entities:

public class Student {

@Id
@GeneratedValue
private Long id;

@NotBlank
@Size(min = 5, max = 64)
@Column(unique=true)
private String nickname;

@NotBlank
@Email
@Column(unique=true)
private String email;

@NotBlank
@Size(min = 8, max = 64)
private String password;

@ManyToMany(mappedBy = "students", fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
private Set<StudyGroup> studyGroups;

}

And

public class StudyGroup {

@Id
@GeneratedValue
private Long id;

@NotBlank
private String name;

@ManyToOne
private Student creator;

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
private Set<Notification> notifications;

@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
private Set<Student> students;

}

I know of three different ways to fetch the relations.

  1. Fetch the study groups from the student by fetching the student and the using student.getStudyGroups();

  2. Using projection. Something like:

     ReturnStudyGroups findStudentById(Long id);
    
     interface ReturnStudyGroups {
         Set<StudyGroup> getStudyGroups();
     }
    
  3. In the study group repository, making a custom query that searches for study groups that have the student in the students field.

What is the best way for fetching the relations? Is projection faster then the first method mentioned?

Fambo
  • 96
  • 3
  • 5

2 Answers2

0

What is the best way for fetching the relations? Is projection faster then the first method mentioned?

Depends on what is your use case and expectations. Sometimes it will be better to lazy load StudyGroup, and sometimes it's better to avoid that and load all the data at once.

I assume you want to fetch the data at once. Then I would suggest the 3rd approach using simple JPQL custom query:

@Query("FROM Student s FETCH JOIN s.studyGroups")
Set<Student> findAllFetchStudyGroups();

(may contain syntax errors, I didn't check it)

Btw.

@ManyToMany(mappedBy = "students", fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
private Set<StudyGroup> studyGroups;

As far as I know if using Spring Data repositories, the FetchType is ignored.

Marcin Kunert
  • 5,596
  • 5
  • 26
  • 52
  • Thanks for the response. So, whenever I need to fetch relations of an entity I should make a custom query like that? – Fambo Mar 08 '22 at 13:09
  • @Fambo yes, or you could use entity graph like shown here: https://stackoverflow.com/a/29651595/1756721 – Marcin Kunert Mar 09 '22 at 09:05
0

My experience showed me over the years that :

  1. make all relations between objects lazy , it's the most flexible approach and keeps the performance optimal.
  2. create as many custom queries as needed with join fetches to fetch only what data you need when you need them.

There are some cool libraries that offer even better functionality like this one https://github.com/Blazebit/blaze-persistence

It offers some cool features that jpa / hibernate do not offer by them selves.

XII
  • 420
  • 4
  • 16