우리는 (최대 절전 모드 등, 봄 DataJPA으로) 새로운 프로젝트에 대한 graphql - SPQR 및 graphql - SPQR 스프링 부팅-스타터를 사용하고 있습니다.
우리는이 같은 돌연변이를 가지고 :
@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: {...}
그들이 중요하지 않은 것처럼 나는 변수를 ommitted있다. 나는 그것을 변경하는 경우는 작동하지 않습니다
mutation createMatch ($matchForm: MatchFormInput!){
match: createMatch(matchForm: $matchForm) {
id
homeTeam {
name
}
}
variables: {...}
나는 LazyInitalizationException을 얻고 나는 이유를 알고 :
homeTeam는 ID에 의해 참조에 의해로드됩니다 teamRepository
. 반환 된 팀은 단지 최대 절전 모드 프록시입니다. 새로운 일치를 저장하는 미세 어느 아무것도 더 필요하지 않습니다. 그러나 결과를 다시 보내는 GraphQL 프록시에 액세스해야하고 () match.team.getName를 호출합니다. 하지만이 표시된 거래 분명히 외부에서 발생 @Transactional
.
나는 팀 homeTeam teamRepository.findById (matchForm.getHomeId ())로 고칠 수 OrElse라는 (NULL을).; match.setHomeTeam (homeTeam);
Hibernate는 더 이상 프록시하지만, 실제 개체를로드하지 않습니다. 나는 GraphQL 쿼리 정확히 요구되는 알고하지 않는 한이 나중에 필요하지 않은 경우 간절히 모든 데이터를로드하려면, 그것은 이해가되지 않습니다. GraphQL가 내부에서 실행 될 수 있다면 좋을 것 @Transactional
I는 각 쿼리와 돌연변이의 트랜잭션 경계를 정의 할 수 있습니다.
이에 대한 모든 추천?
PS : 나는 코드를 제거하고보다 간결하게 정리 작업을했다. 그래서 코드는 실행 가능하지 않을 수도 있지만, 문제를 설명 않습니다.
난 당신이 고려할 수 있습니다 몇 가지와 함께 올 수 있습니다.
필요에 따라 1) 간절 부하
당신은 항상 선제 적 쿼리 욕구 필드 것을 확인하고 열망을로드 할 수 있습니다. 세부 사항뿐만 아니라 설명 미리보고 건물 효율적인 데이터에는 Fetcher graphql - 자바의 블로그에 기사를.
즉, 당신은 전화 얻을 수 있습니다 DataFetchingEnvironment#getSelectionSet()
당신을 줄 것이다 DataFetchingFieldSelectionSet
그리고 당신이 최적화 로딩에 필요한 모든 정보를 포함합니다.
SPQR에서, 당신은 항상의 보류 얻을 수 있습니다 DataFetchingEnvironment
주입하여 (그리고 많은 이상) ResolutionEnvironment
:
@GraphQLMutation
public Match createMatch(
@NotNull @Valid MatchForm matchForm,
@GraphQLEnvironment ResolutionEnvironment env) { ... }
당신은 단지 1 수준 서브 필드의 이름을해야하는 경우 삽입 할 수
@GraphQLEnvironment Set<String> selection
대신.
테스트 용이성을 위해, 당신은 항상 자신에 연결할 수 있습니다 ArgumentInjector
이 테스트에서 조롱 쉽게 그래서, 체리 픽 정확히 당신이 필요 주입 것이다.
2) 트랜잭션의 전체 GraphQL 쿼리 해상도를 실행
대신에 또는 필요에 추가하여 @Transactional
개별 리졸버에, 당신은 트랜잭션의 전체 일을 실행하는 하나의 기본 컨트롤러를 대체 할 수 있습니다. 그냥 때리고 @Transactional
컨트롤러 방법에, 그리고 넌 좋은 이동합니다.