graphql-spqr con la primavera y de arranque transaccional de Límites

Janning:

Estamos utilizando graphql-SPQR y graphql-SPQR-primavera-arranque-motor de arranque para un nuevo proyecto (Con la primavera DataJPA, hibernación y así sucesivamente).

Tenemos una mutación de esta manera:

@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;
}

Esta mutación funciona bien:

mutation createMatch ($matchForm: MatchFormInput!){   
  match: createMatch(matchForm: $matchForm) {       
    id
}
variables: {...}

He omitido las variables, ya que no son importantes. No funciona si la cambio a:

mutation createMatch ($matchForm: MatchFormInput!){   
  match: createMatch(matchForm: $matchForm) {       
    id
    homeTeam {
       name
    }
 }
variables: {...}

Consigo un LazyInitalizationException y sé por qué:

El Hometeam es referenciado por un ID y es cargado por teamRepository. El equipo devuelto es sólo un indicador de hibernación. Lo cual está muy bien para guardar el nuevo ajuste, nada se necesita más. Pero para devolver el resultado GraphQL necesita para acceder al proxy y llama match.team.getName (). Pero esto sucede, obviamente, fuera de la transacción marcada con @Transactional.

Lo puedo arreglar con el equipo hometeam teamRepository.findById (matchForm.getHomeId ()) OrElse (nulo).; match.setHomeTeam (Hometeam);

Hibernate ya no está cargando un proxy, pero el objeto real. Pero como yo no sé lo que la consulta GraphQL exactamente está pidiendo, no tiene sentido cargar con entusiasmo todos los datos si no se necesita más adelante. Sería bueno si GraphQL sería ejecutado dentro de la @Transactional, por lo que puede definir los límites de transacción para cada consulta y la mutación.

Cualquier recomendación para esto?

PD: Me quitó el código e hizo algo de limpieza para que sea más concisa. por lo que el código no sea ejecutable, pero sirve para ilustrar el problema.

kaqqao:

Puedo venir con un par de cosas que usted puede tener en cuenta.

1) de carga con impaciencia como sea necesario

Siempre se puede comprobar qué campos preventivamente las necesidades de consulta y con entusiasmo cargarlos. Los detalles, así explican en las Fetchers de datos eficiente de construcción con la vista puesta artículo en el blog graphql-java.

En resumen, se puede obtener la llamada DataFetchingEnvironment#getSelectionSet()que le dará DataFetchingFieldSelectionSety que contiene toda la información que necesita para optimizar la carga.

En SPQR, siempre se puede obtener una bodega de DataFetchingEnvironment(y mucho más) mediante la inyección ResolutionEnvironment:

@GraphQLMutation
public Match createMatch(
           @NotNull @Valid MatchForm matchForm,
           @GraphQLEnvironment ResolutionEnvironment env) { ... }

Si sólo necesita los nombres de los subcampos primero nivel, puede inyectarse

@GraphQLEnvironment Set<String> selection

en lugar.

Para la capacidad de prueba, siempre se puede cablear en su propia ArgumentInjectorque cherry-picks exactamente lo que necesita inyectarse, por lo que es más fácil burlarse de pruebas.

2) Ejecutar toda la consulta de resolución GraphQL en una transacción

En lugar de o además de tener @Transactionalen resolutores individuales, se puede sustituir el controlador por defecto con uno que recorre toda la cosa en una transacción. Sólo una palmada @Transactionalen el método controlador, y ya está bueno para ir.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=365465&siteId=1
Recomendado
Clasificación