У меня есть проект Spring Boot, использующий базу данных mysql. У него есть модель данных (Project
), которая имеет отношение «один ко многим» с другой моделью (Files
), указанная с подходом выборки FetchType.LAZY
.
@Entity
public class Project extends BaseEntity {
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="projectId")
private List<Files> files;
...
}
У меня есть конечная точка, которая сериализует список проектов до JSON /projects
. И еще одна конечная точка, которая предоставляет мне детали из одного проекта /projects/[projectid]
. Мне не нужен список Files
для каждого Project
для первой конечной точки. Но я делаю для последнего.
Чтобы позволить мне определить, следует ли извлекать Files
, связанный с проектом, на уровне контроллера, я создал фильтр для конечной точки /projects
, чтобы вырезать поле files
JSON, следуя некоторым указаниям в этом вопросе: Игнорировать поля из Java объекта динамически при отправке как JSON из Spring MVC
Чтобы моя модель Project выглядела следующим образом:
@JsonFilter("FilterOutFiles")
@Entity
public class Project extends BaseEntity{
...
}
и конечная точка контроллера следующим образом:
@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;
}
...
}
Кажется, это хорошо работает при удалении списка файлов из JSON , Нет проблем там. Мое предположение состояло в том, что с типом выборки, установленным на «ленивый», извлечение файлов будет происходить только во время сериализации (если требуется!), И с его фильтрацией сериализатором это не потребуется, поэтому не будет
В процессе выполнения функции контроллера я вижу один SQL запрос на получение списка проектов при вызове projectRepository.findAllByOwner_UserId
. Что, как и ожидалось. Однако, похоже, что после возврата из функции контроллера (я полагаю, во время процесса сериализации), hibernate делает запросы для получения списка файлов для каждого проекта. Один запрос для каждого проекта. Поскольку сами файлы также имеют отношения «один ко многим» с другими моделями, это быстро приводит к появлению сотен, а иногда и тысяч операторов SELECT. Вместо одного.
Как я могу помешать Hibernate разрешить эту отложенную выборку для данных, которые мне не нужны, которые теперь отфильтрованы сериализатором?