Мы используем graphql-spqr и graphql-spqr-spring-boot-starter для нового проекта (с Spring DataJPA, hibernate и т. Д.).
У нас есть мутация, подобная этой:
@Transactional
@GraphQLMutation
public Match createMatch(@NotNull @Valid MatchForm matchForm) {
Match match = new Match(matchForm.getDate());
match.setHomeTeam(teamRepository.getOne(matchForm.getHomeId()));
match.setAwayTeam(teamRepository.getOne(matchForm.getAwayId()));
match.setResult(matchForm.getResult());
matchRepository.save(match);
return match;
}
Эта мутация работает нормально:
mutation createMatch ($matchForm: MatchFormInput!){
match: createMatch(matchForm: $matchForm) {
id
}
variables: {...}
Я пропустил переменные, поскольку они не важны. Он не работает, если я изменяю его на:
mutation createMatch ($matchForm: MatchFormInput!){
match: createMatch(matchForm: $matchForm) {
id
homeTeam {
name
}
}
variables: {...}
Я получаю исключение LazyInitalizationException и знаю, почему:
На homeTeam ссылается идентификатор и загружается teamRepository
. Возвращенная команда - это только прокси в спящем режиме. Что хорошо для сохранения нового матча, больше ничего не нужно. Но для отправки результата GraphQL необходимо получить доступ к прокси и вызвать match.team.getName (). Но это происходит, очевидно, за пределами транзакции, помеченной @Transactional
.
. Я могу это исправить с помощью Team homeTeam teamRepository.findById (matchForm.getHomeId ()). OrElse (null); match.setHomeTeam (homeTeam);
Hibernate больше не загружает прокси, а реальный объект. Но поскольку я не знаю, что именно запрашивает запрос GraphQL, не имеет смысла загружать все данные, если в дальнейшем они не нужны. Было бы неплохо, если бы GraphQL выполнялся внутри @Transactional
, поэтому я могу определить границы транзакций для каждого запроса и мутации.
Любая рекомендация для этого?
PS: я удалил код и сделал некоторую очистку, чтобы сделать его более кратким. поэтому код может не выполняться, но он иллюстрирует проблему.