使用graphql-spring的LazyInitializationException

我目前正在将我的REST服务器迁移到GraphQL(至少部分).大部分工作已经完成,但我偶然发现了这个问题,我似乎无法解决这个问题:在Graphql查询中使用FetchType.LAZY的OneToMany关系.

我在用:
https://github.com/graphql-java/graphql-spring-boot

https://github.com/graphql-java/graphql-java-tools为整合.

这是一个例子:

实体:

@Entity
class Show {
   private Long id;
   private String name;

   @OneToMany
   private List<Competition> competition;
}

@Entity
class Competition {
   private Long id;
   private String name;
}

架构:

type Show {
    id: ID!
    name: String!
    competitions: [Competition]
}

type Competition {
    id: ID!
    name: String
}

extend type Query {
    shows : [Show]
}

解析器:

@Component
public class ShowResolver implements GraphQLQueryResolver {
    @Autowired    
    private ShowRepository showRepository;

    public List<Show> getShows() {
        return ((List<Show>)showRepository.findAll());
    }
}

如果我现在使用此(简写)查询查询端点:

{
  shows {
    id
    name
    competitions {
      id
    }
  }
}

我得到:

org.hibernate.LazyInitializationException: failed to lazily initialize
a collection of role: Show.competitions, could not initialize proxy –
no Session

现在我知道为什么会出现这个错误以及它意味着什么,但我真的不知道应该为此修复.我不想让我的热衷于急切地获取所有关系,因为这会否定GraphQL的一些优点.我可能需要寻找解决方案的任何想法?
谢谢!

解决方法:

我解决了它,我应该更仔细地阅读graphql-java-tools库的文档.
除了解析基本查询的GraphQLQueryResolver之外,我还需要GraphQLResolver< T>.对于我的Showclass,看起来像这样:

@Component
public class ShowResolver implements GraphQLResolver<Show> {
    @Autowired
    private CompetitionRepository competitionRepository;

    public List<Competition> competitions(Show show) {
        return ((List<Competition>)competitionRepository.findByShowId(show.getId()));
    }
}

这告诉库如何解析我的Showclass中的复杂对象,并且仅在最初的查询请求包含Competitionobjects时使用.新年快乐!

编辑:这里要求的是使用自定义执行策略的另一种解决方案.我正在使用graphql-spring-boot-starter和graphql-java-tools:

我首先定义一个GraphQL配置,如下所示:

@Configuration
public class GraphQLConfig {
    @Bean
    public Map<String, ExecutionStrategy> executionStrategies() {
        Map<String, ExecutionStrategy> executionStrategyMap = new HashMap<>();
        executionStrategyMap.put("queryExecutionStrategy", new AsyncTransactionalExecutionStrategy());
        return executionStrategyMap;
    }
}

其中AsyncTransactionalExecutionStrategy的定义如下:

@Service
public class AsyncTransactionalExecutionStrategy extends AsyncExecutionStrategy {

    @Override
    @Transactional
    public CompletableFuture<ExecutionResult> execute(ExecutionContext executionContext, ExecutionStrategyParameters parameters) throws NonNullableFieldWasNullException {
        return super.execute(executionContext, parameters);
    }
}

这将查询的整个执行放在同一个事务中.我不知道这是否是最佳解决方案,并且它在错误处理方面也有一些缺点,但您不需要以这种方式定义类型解析器.

上一篇:GraphQL Part I: hello, world.


下一篇:java – 将bean注入GraphQL的DataFetcher