Spring for GraphQL with Querydsl
Spring team provides a very powerful yet easy-to-create setup, that allows for creating an API that fetches data directly from the database.
This tutorial is based on an application responsible for managing information about customers and their purchase transactions. All data resides in the SQL database that has two tables: customers
and purchase_transaction
.
The application is a Java Spring Boot application with GraphQL and JPA connected to an H2 database. Querydsl will serve as a “link” that connects GraphQL query with JPA because it expresses query predicates by generating a meta-model. And it is done by using annotation processors. To make it easy to test I've created a class that populates the database with random values.
The complete code and dependencies needed to run this project you can find below:
1. A setup with minimal configuration
I’ll show you first how to do a setup with minimal configuration. First, we have to create a JPA repository that returns an entity mapped to a customers
table. This repository has to extend CrudRepository
and QuerydslPredicateExecutor
and be annotated with @GraphQlRepository
.
The next step is to create a GraphQL schema file with queries that will be directly translated to this repository.
type Query {
# CUSTOMERS
findAllCustomers : [CustomerEntity]
findCustomerById ( id : String!) : CustomerEntity
}type CustomerEntity {
id : String
fullName : String
phoneNumber : String
address : String
createdAt : Date
purchaseTransactions : [PurchaseTransactionEntity]
}
type PurchaseTransactionEntity {
id : String
paymentType : String
amount : Float
createdAt : Date
}
That is actually all that we have to do. Here I've mapped 2 queries: the first one will return a list of all customers and the second will fetch the customer from a database with provided in the query id.
2. More advanced setup
Let's say we have a requirement for an API that should fetch data from purchase_transacions
table, but this API cant return an exact entity but rather a DTO with the possibility to limit the fields returned by this DTO. In our case, an API won't return a field amount.
To achieve these requirements we can use projections. Projections provide a way to transform query results before returning to a consumer of API. Instead of returning objects fromPurchaseTransactionEntity
the projection below will be returned:
As in the previous example, we have to create a repository and describe queries in a schema file, one to return a list of all purchase transactions, and one to fetch a transaction by id:
The
DataFetcher
builds a QuerydslPredicate
from GraphQL request parameters, and uses it to fetch data.
The quote above is from the official Spring documentation, so consider this rule when creating queries.
As these queries won't return entities but projections we have to configure a data fetcher for each API like the below:
Configurations are straightforward and consist of data fetcher creations for each query and then adding it to RuntimeWiringConfigurer
.
The project has a folder with a Postman collection, so you can run it yourself. The short demo video shows you how it works:
Conclusion
This tutorial was about a simple yet powerful setup that allows the creation of GraphQL API connected directly to a database with minimal effort. Also, I recommend checking the official documentation. Thank you for reading! If you have any questions or suggestions, please feel free to write me on my LinkedIn account.