봄 부팅 및 트랜잭션 경계와 graphql - SPQR

Janning :

우리는 (최대 절전 모드 등, 봄 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가 내부에서 실행 될 수 있다면 좋을 것 @TransactionalI는 각 쿼리와 돌연변이의 트랜잭션 경계를 정의 할 수 있습니다.

이에 대한 모든 추천?

PS : 나는 코드를 제거하고보다 간결하게 정리 작업을했다. 그래서 코드는 실행 가능하지 않을 수도 있지만, 문제를 설명 않습니다.

kaqqao :

난 당신이 고려할 수 있습니다 몇 가지와 함께 올 수 있습니다.

필요에 따라 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컨트롤러 방법에, 그리고 넌 좋은 이동합니다.

추천

출처http://43.154.161.224:23101/article/api/json?id=365474&siteId=1