I am developing an application using Spring Boot and GraphQL. When returning an Entity directly from GraphQL, data fetchers automatically handle the queries, fetching only the tables requested in the GraphQL query.
For instance:
query Workspace {
workspace {
id
}
}
This will only query the workspace
table.
query Workspace {
workspace {
id
users {
id
}
}
}
This will query both the workspace
and user
tables.
However, when I return a DTO, because I explicitly call getUsers
in my transformation logic, it fetches the users as well, leading to unnecessary database calls.
Here are my JPA Entities:
@Entity
public class Workspace {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "workspace", fetch = FetchType.LAZY)
private Set<User> users;
}
@Entity
public class User {
private String fullName;
@ManyToOne(fetch = FetchType.LAZY)
private Workspace workspace;
}
This is my service layer method:
public WorkspacePayload getWorkspace() {
Workspace workspace = workspaceRepository.findById(1L)
.orElseThrow(() -> new GraphQLException("Workspace not found"));
return WorkspaceUtil.prepareWorkspacePayload(workspace);
}
And the transformation logic:
public WorkspacePayload prepareWorkspacePayload(Workspace workspace) {
return WorkspacePayload.builder()
.id(workspace.getId())
.name(workspace.getName())
.users(getUsers(workspace))
.build();
}
private List<UserPayload> getUsers(Workspace workspace) {
return workspace.getUsers().stream()
.map(workspaceUser -> UserPayload.builder()
.id(workspaceUser.getId())
.fullName(workspaceUser.getFullName())
.build())
.collect(Collectors.toList());
}
My challenge: How can I optimize my service layer to ensure that I don’t make unnecessary database queries when I want to return DTOs instead of entities? What is the best practice for this scenario?