3

I am new to Graphql and looking into creating a proof of concept to see how it works. I am using Spring Boot (2.2.2.RELEASE) and bringing in the graphql-spring-boot-starter.

<dependency>
    <groupId>com.graphql-java-kickstart</groupId>
    <artifactId>graphql-spring-boot-starter</artifactId>
    <version>6.0.1</version>
</dependency>

I have setup my graphql schema as a file on the classpath with the following configuration:

type Order {
  orderNumber: ID!
  customers: [Customer]
  items: [Item]
}

type Customer {
  customerNumber: ID!
  fullName: String
  postalAddresses: [PostalAddress]
}

type PostalAddress {
  line1: String
  line2: String
  city: String
  stateCode: String
  postalCode: String
  postalCodeExtension: String
  countryCode: String
}

type Item {
  itemId: ID!
  fullDescription: String
}

type Query {
  findOrdersByCustomerNumber(customerNumber: String): [Order]
}

I have created a root Query class:

@Component
public class Query implements GraphQLQueryResolver {
    private OrderService orderService;

    @Autowired
    public Query(OrderService orderService) {
        this.orderService = orderService;
    }

    public List<Order> findOrdersByCustomerNumber(String customerNumber) {
        return this.orderService.findOrdersByCustomerNumber(customerNumber);
    }
}

And here is my Order resolver:

@Component
public class OrderResolver implements GraphQLResolver<Order> {
    private ItemRepository itemRepository;
    private CustomerRepository customerRepository;

    @Autowired
    public OrderResolver(CustomerRepository customerRepository, ItemRepository itemRepository) {
        this.customerRepository = customerRepository;
        this.itemRepository = itemRepository;
    }

    public List<Item> item(Order order) {
        return itemRepository.findItemsByOrderNumber(order.getOrderNumber());
    }

    public List<Customer> customers(Order order) {
        return customerRepository.findCustomersByOrderNumber(order.getOrderNumber());
    }
}

Everything seems to work fine and I can send a graphql request and get a response. It was actually really easy to implement and impressed with how quickly this library allowed me to do that.

However, here is my issue. It's the dreaded n+1 SQL issue.

So, when I have customer with 162 orders.

  1 = Driver SQL (get all the orders for the customer number)
162 = Customer SQL (One query is fired off for each order and it's same customer for each select)
162 = Postal Address SQL (One query is fired off for each customer...note, not included in the code snippets)
162 = Item SQL (assume one item per order).

So, that totals 487 SQL queries. And as a result, this has performance implications. I am using straight JDBC to query the database (no JPA or ORM's at the moment).

My questions is how can I get hold of the GraphQL request in the root Query resolver so that can manipulate the SQL for the dependent objects in the graph? When doing some research, I see that in the Node/Javacript world, there a dataloader utility that can help address this issue (https://github.com/graphql/dataloader)

So, I am unclear on how to solve this with this java implementation. If anyone has any suggestions or sample code, that would be really helpful to see if this POC has any merit.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Dan DaLuga
  • 85
  • 2
  • 10
  • Have you had a look at https://github.com/graphql-java/java-dataloader, its the java implementation of the graphl/dataloader you mentioned. My advice would be to use DTO instead of directly retrieving domain entities. You can decide which field the DTO should eager/lazy-load from the domain object – AllirionX Jan 21 '20 at 23:11
  • Did you find any solution? – Stuck Apr 26 '20 at 22:57
  • Yes, I ended up doing what was documented [here](https://stackoverflow.com/questions/62093189/graphql-and-data-loader-using-the-graphql-java-kickstart-library/62136495#62136495) – Dan DaLuga Jun 01 '20 at 16:25
  • Another approach (besides DataLoader) is to form SQL query on the fly depending on the fields in GraphQL request. Take a look at this [article by Piotr Mińkowski](https://piotrminkowski.com/2020/07/31/an-advanced-guide-to-graphql-with-spring-boot/) where he utilizes `Specification` classes with JPA Criteria API. – Ilya Serbis Aug 23 '20 at 22:52
  • Where is the connection between your `Query` and `OrderResolver` ? or by `OrderService` , do you mean `OrderResolver`? – RamPrakash Jun 28 '22 at 14:52

0 Answers0