I have a Spring Boot project using a mysql database. It has a data model (Project
) that has a one-to-many relationship with another model (Files
), specified with a fetching approach of FetchType.LAZY
.
@Entity
public class Project extends BaseEntity {
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="projectId")
private List<Files> files;
...
}
I have an endpoint that serializes a list of projects to JSON /projects
. And another endpoint that provides me with the details from a single project /projects/[projectid]
. I do not need the list of Files
for each and every Project
for the first endpoint. But I do for the latter.
To allow me to determine whether to fetch the Files
associated with a project at the controller-level, I have created a filter for the /projects
endpoint, to strip out the files
JSON field, Following some of the guidance in the question here: Ignore fields from Java object dynamically while sending as JSON from Spring MVC
Making my Project model look like this:
@JsonFilter("FilterOutFiles")
@Entity
public class Project extends BaseEntity{
...
}
and the controller's endpoint as so:
@Slf4j
@RestController
public class ProjectsController {
...
@JsonRequestMapping(value = "/projects", method = RequestMethod.GET)
public MappingJacksonValue getUserProjects(@CurrentAccount final UserRuntime userRuntime) {
User user = userRuntime.getUser();
List<Project> ownProjectList = projectRepository.findAllByOwner_UserId(user.getId());
SimpleFilterProvider filters = new SimpleFilterProvider();
filters.addFilter("FilterOutFiles", SimpleBeanPropertyFilter.serializeAllExcept("files"));
MappingJacksonValue mapping = new MappingJacksonValue(ownProjectList);
mapping.setFilters(filters);
return mapping;
}
...
}
This seems to work fine in stripping out the list of files from the JSON. No problem there. My assumption was that with the fetch type set to "lazy" the retrieval of the files would only happen during serialization (if required!), and with it filtered out by the serializer, it wouldn't be required, therefore wouldn't be fetched.
In the course of executing the controller's function, I can see one SQL request to get the list of projects when calling projectRepository.findAllByOwner_UserId
. Which is as expected. However, it seems that after returning from my controller function (I presume during the serializing process), hibernate makes queries to retrieve the list of files for each project. One query for each project. Because files themselves also have one-to-many relationships with other models, this quickly balloons into hundreds, sometimes thousands of SELECT statements. Instead of just one.
How can I prevent Hibernate from resolving this lazy fetch on data I do not require which has now been filtered out by the serializer?