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