网上的graphql使用dataloader的demo大都是kotlin加上gradle的,
搜不到能用的maven构建的java的demo,很难受:(
因为是dataloader的demo,所以就只有查询的功能,没有新增修改的功能,
主要就是findAllBooks,先查book,再查author,如果不用dataloader,会发生n+1问题,现在使用了dataloader,查author的时候,是收集了bookList里面每个book的authorId,然后最后汇总查询的。
代码如下:
maven依赖如下,都是找的当前最高版本的maven依赖
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.2.4</version>
<groupId>com.graphql-java</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>5.0.2</version>
GraphqlApplication.java
@SpringBootApplication
public class GraphqlApplication {
public static void main(String[] args) {
SpringApplication.run(GraphqlApplication.class, args);
}
}
schema.graphqls
type Author {
id: Long!
firstName: String
lastName: String
}
type Book {
id: Long!
title: String!
isbn: String!
pageCount: Int
author: Author
}
root.graphqls
type Query {
findAllBooks: [Book]!
}
type Mutation {
}
Query.java,
@Component
public class Query implements GraphQLQueryResolver {
public List<Book> findAllBooks() {
return BookRepo.findAll();
}
}
Mutation.java, mutation什么功能都没有实现
@Component
public class Mutation implements GraphQLMutationResolver {
}
BookResolver.java
@Component
public class BookResolver implements GraphQLResolver<Book> {
public CompletableFuture<Author> getAuthor(Book book, DataFetchingEnvironment environment) {
//应该从environment中获取AuthorDataLoader的,但是environment里面暂时没找到authorLoader,所以变通了一下,使用了一个全局变量的dataloader
return AuthorDataLoader.INSTANCE.load(book.getAuthorId());
}
}
AuthorResolver.java
@Component
public class AuthorResolver implements GraphQLResolver<Author> {
}
AuthorRepo.java
public class AuthorRepo {
public static Map<Long, Author> authorMap = new HashMap<>();
static {
authorMap.put(1L, new Author(1L, "zhi", "chi"));
authorMap.put(2L, new Author(2L, "lu", "xun"));
}
public static List<Author> findAllById(List<Long> idList) {
List<Author> authorList = new ArrayList<>();
for (Long id : idList) {
authorList.add(authorMap.get(id));
}
return authorList;
}
}
BookRepo.java
public class BookRepo {
public static Map<Long, Book> bookMap = new HashMap<>();
static {
bookMap.put(1L, new Book(1L, "成功学", "1234", 56, 1L));
bookMap.put(2L, new Book(2L, "失败时成功之母", "1234778", 65, 2L));
}
public static List<Book> findAll() {
return new ArrayList(bookMap.values()); }
}
AuthorDataLoader.java
public class AuthorDataLoader extends DataLoader<Long, Author> {
public static AuthorDataLoader INSTANCE = new AuthorDataLoader();
public AuthorDataLoader() {
super((BatchLoader) keys -> CompletableFuture.supplyAsync(() -> AuthorRepo.findAllById(keys)),
DataLoaderOptions.newOptions().setCachingEnabled(false));
}
}
把dataloader配置到GraphQL环境中,GraphQLConfig
@Configuration
public class GraphQLConfig {
@Bean
public Instrumentation instrumentation() {
DataLoaderRegistry dataLoaderRegistry = new DataLoaderRegistry();
dataLoaderRegistry.register("author", DataLoaderFact.getBatchLoader());
DataLoaderDispatcherInstrumentation dispatcherInstrumentation
= new DataLoaderDispatcherInstrumentation(dataLoaderRegistry);
return new ChainedInstrumentation(Arrays.asList(
dispatcherInstrumentation,
new MaxQueryComplexityInstrumentation(100),
new MaxQueryDepthInstrumentation(10)
));
}
}
整个项目跑起来,
输入:
{
findAllBooks { id, title, author { firstName } }
}
输出:
{
"data": {
"findAllBooks": [
{
"id": 1,
"title": "成功学",
"author": {
"firstName": "zhi"
}
},
{
"id": 2,
"title": "失败时成功之母",
"author": {
"firstName": "lu"
}
}
]
}
}