- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们正在将 graphql-spqr 和 graphql-spqr-spring-boot-starter 用于一个新项目(使用 Spring DataJPA、hibernate 等)。
我们有这样的突变:
@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: {...}
我省略了变量,因为它们并不重要。如果我将其更改为:
mutation createMatch ($matchForm: MatchFormInput!){
match: createMatch(matchForm: $matchForm) {
id
homeTeam {
name
}
}
variables: {...}
我收到 LazyInitalizationException,我知道为什么:
homeTeam 由 ID 引用并由 teamRepository
加载。返回的团队只是一个 hibernate 代理。这对于保存新的比赛来说很好,不需要更多。但为了发回结果,GraphQL 需要访问代理并调用 match.team.getName()。但这显然发生在用 @Transactional
标记的事务之外。
我可以用以下方法修复它 团队 homeTeam teamRepository.findById(matchForm.getHomeId()).orElse(null); match.setHomeTeam(homeTeam);
Hibernate 不再加载代理,而是加载真实对象。但由于我不知道 GraphQL 查询到底要求什么,如果以后不需要的话,急切地加载所有数据是没有意义的。如果 GraphQL 在 @Transactional
内执行,那就太好了,这样我就可以为每个查询和突变定义事务边界。
对此有什么建议吗?
PS:我剥离了代码并进行了一些清理以使其更加简洁。因此代码可能无法运行,但确实说明了问题。
最佳答案
@kaqqao 的回答非常好,但我想对此发表评论并展示第三种解决方案:
我不喜欢这个解决方案,因为我必须在我真的不关心的环境中做很多工作。这不是 GraphQL 的目的。如果需要,应该进行解决。展望每个 GraphQL 查询以及路径的各个方向,对我来说听起来很奇怪。
我设法通过服务类来实现这一点。但是您会遇到异常问题,因为异常被包装并且未正确处理。
public class TransactionalGraphQLExecutor implements GraphQLServletExecutor {
private final ServletContextFactory contextFactory;
@Autowired(required = false)
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
private DataLoaderRegistryFactory dataLoaderRegistryFactory;
private final TxGraphQLExecutor txGraphQLExecutor;
public TransactionalGraphQLExecutor(ServletContextFactory contextFactory, TxGraphQLExecutor txGraphQLExecutor) {
this.contextFactory = contextFactory;
this.txGraphQLExecutor = txGraphQLExecutor;
}
@Override
public Map<String, Object> execute(GraphQL graphQL, GraphQLRequest graphQLRequest, NativeWebRequest nativeRequest) {
ExecutionInput executionInput = buildInput(graphQLRequest, nativeRequest, contextFactory, dataLoaderRegistryFactory);
if (graphQLRequest.getQuery().startsWith("mutation")) {
return txGraphQLExecutor.executeReadWrite(graphQL, executionInput);
} else {
return txGraphQLExecutor.executeReadOnly(graphQL, executionInput);
}
}
}
public class TxGraphQLExecutor {
@Transactional
public Map<String, Object> executeReadWrite(GraphQL graphQL, ExecutionInput executionInput) {
return graphQL.execute(executionInput).toSpecification();
}
@Transactional(readOnly = true)
public Map<String, Object> executeReadOnly(GraphQL graphQL, ExecutionInput executionInput) {
return graphQL.execute(executionInput).toSpecification();
}
}
也可以进行检测,请参阅 https://spectrum.chat/graphql/general/transactional-queries-with-spring~47749680-3bb7-4508-8935-1d20d04d0c6a
目前我最喜欢的是拥有另一个手动解析器
@GraphQLQuery
@Transactional(readOnly = true)
public Team getHomeTeam(@GraphQLContext Match match) {
return matchRepository.getOne(match.getId()).getHomeTeam();
}
当然你也可以设置spring.jpa.open-in-view=false
(反模式)
或者您可以急切地获取。
如果您可以使用 GraphQL 定义事务边界,那就太好了。
关于java - 具有 Spring Boot 和事务边界的 graphql-spqr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60873340/
有没有办法检索客户端在 GraphQL 查询中请求的字段列表? 假设我有以下类型: type Book { isbn: String title: String genre: String
我用 io.leangen.graphql.spqr库版本0.9.6我需要从 Query 中排除突变根节点进入文档。 我的 GraphQLController.kt看起来像这样: @RestContr
目前,我抛出 RuntimeException 来返回 GraphQL 验证错误。它的工作效果出奇的好,除了它在我的日志中抛出大量堆栈跟踪的可怕错误之外。 在这里您可以看到我正在检查提交的新用户注册突
使用 SQPR 构建 graphQL API。我有大量数据集合,想逐页加载数据。使用 SQPR 执行此操作的推荐方法是什么?从客户端(查询)来看它会是什么样子? 此外,请记住将 Apollo 客户端作
我graphql-spqr,java.util.Date被定义为标量。是否可以覆盖 java.util.Date 的序列化/反序列化以获得日期的不同字符串表示形式? 本文中提到的ScalarStrat
能够扩展现有类型是非常棒的,因为它允许代码模块化和权限分离。我找到了关于如何扩展查询中的对象输出的好例子(见下文),但没有好的方法来扩展给定对象的输入。 为了举例,假设我们有一个类User。 clas
如何使用 Graphql SPQR 库实现 GraphQL 的订阅功能? 最佳答案 一般来说,你只需要用 @GraphQLSubscription 注释一个方法。并确保该方法返回 org.reacti
我有以下带有自定义属性的数据模型: class Foo { private Long id; private Set attributes; } cla
我收到以下信息,但似乎找不到答案。 Error [ValidationError{validationErrorType=FieldUndefined, queryPath=[find_by_id],
我使用 GraphQL SPQR与实体 @Entity public class MyEntity { @Id @GeneratedValue(strategy = Generatio
我想在服务类中返回 JSON 文字 @GraphQLQuery(name = "renderUI", description = "Schema for your form") public Stri
我们正在将 graphql-spqr 和 graphql-spqr-spring-boot-starter 用于一个新项目(使用 Spring DataJPA、hibernate 等)。 我们有这样的
我正在尝试为我的 spring-boot/graphQL/SPQR 项目创建一些身份验证机制。我设法通过 @GraphQLRootContext 注释在单个服务方法上完成它: @GraphQLMuta
我注意到 GraphQL-SPQR 至少有几个可以配置的属性(例如 graphql.spqr.gui.enabled=true)。是否有配置指定使用 Gson 而不是 Jackson 进行对象序列化/
没有标准来表示NaN和 INFINITY Graphql 都不在以及 JSON . 在 JavaScript 中,JSON.stringify(0/0) 和 JSON.stringify(1/0) 将
我正在使用 graphql-spqr-spring-boot-starter库将现有的 Rest API 项目迁移到 GraphQL。我有一段下面的代码来获取当前的 HttpServletReques
我是一名优秀的程序员,十分优秀!