The original address
GraphQL is a query language for the API that allows the client to get exactly the data it needs without any redundancy. GraphQL is a strongly typed protocol, and all data operations are validated against GraphQL Schema.
Add Maven dependencies
Create the sample Spring Boot application and add the following dependencies.
-
graphql-spring-boot-starter
Use to enable the GraphQL controller and make it available in Path/GraphQL. It initializes the GraphQL Schema bean.Copy the code
-
graphql-java
Schemas can be written using the easy-to-understand Graphql Schema language.Copy the code
-
graphiql-spring-boot-starter
Provides a graphical interface that we can use to test GraphQL queries and view query definitions.Copy the code
<dependency> <groupId>com.graphql-java</groupId> <artifactId>graphql-spring-boot-starter</artifactId> < version > 5.0.2 < / version > < / dependency > < the dependency > < groupId > com. Graphql - Java < / groupId > < artifactId > graphql - Java - tools < / artifactId > < version > 5.2.4 < / version > < / dependency > < the dependency > < the groupId > com. Graphql - Java < / groupId > < artifactId > graphiql - spring - the boot - starter < / artifactId > < version > 5.0.2 < / version > </dependency>Copy the code
The following is the complete POM file contents.
<? xml version="1.0" encoding="UTF-8"? > <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < modelVersion > 4.0.0 < / modelVersion > < groupId > com. Techshard. Graphql < / groupId > < artifactId > springboot - graphql < / artifactId > < version > 1.0 - the SNAPSHOT < / version > < the parent > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath /> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.graphql-java</groupId> <artifactId>graphql-spring-boot-starter</artifactId> < version > 5.0.2 < / version > < / dependency > < the dependency > < groupId > com. Graphql - Java < / groupId > < artifactId > graphql - Java - tools < / artifactId > < version > 5.2.4 < / version > < / dependency > < the dependency > < the groupId > com. Graphql - Java < / groupId > < artifactId > graphiql - spring - the boot - starter < / artifactId > < version > 5.0.2 < / version > </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> The < version > 1.18.8 < / version > < optional >true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Copy the code
Create JPA entities and repositories
Next, let’s create a simple entity called Vehicle and the corresponding JPA repository. We’ll write it using Lombok to avoid boilerplate files like getters and setters.
package com.techshard.graphql.dao.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDate;
@Data
@EqualsAndHashCode
@Entity
public class Vehicle implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "ID", nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "type", nullable = false)
private String type;
@Column(name = "model_code", nullable = false)
private String modelCode;
@Column(name = "brand_name")
private String brandName;
@Column(name = "launch_date")
private LocalDate launchDate;
private transient String formattedDate;
// Getter and setter
public String getFormattedDate() {
returngetLaunchDate().toString(); }}Copy the code
Then there is the corresponding JPA repository.
package com.techshard.graphql.dao.repository;
import com.techshard.graphql.dao.entity.Vehicle;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface VehicleRepository extends JpaRepository<Vehicle, Integer> {
}
Copy the code
GraphQL Schema
GraphQL uses its own unique Language to write GraphQL Schema, called Schema Definition Language (SDL). The definition of a schema consists of all API functions available at the endpoint.
A typical example of the GraphQL architecture looks like this:
typeVehicle { id: ID! .type: String,
modelCode: String,
brandName: String,
launchDate: String
}
type Query {
vehicles(count: Int):[Vehicle]
vehicle(id: ID):Vehicle
}
type Mutation {
createVehicle(type: String! , modelCode: String! , brandName: String, launchDate: String):Vehicle }Copy the code
Next, create a folder called GraphQL under SRC /main/ Resources and create your vehicleql.graphqls file under that folder. Copy the above and paste it into your vehicleqL.graphqls file. Note that file names are customizable. Use.graphqls as the file extension.
In the schema above, each object is defined by type. The type system in GraphQL is the most basic component that represents an object that can be retrieved from a service and the fields that that object contains.
In our schema, we have an object called Vehicle as a domain object. The Query type represents a Query for which data can be retrieved from the GraphQL server. Query is interactive and can be modified, and the new results are displayed after the modification. The structure of the query and result is the same. This is important in GraphQL because what you see is what you get.
We’ll see some examples in action later in the article.
The Mutation type is used to represent the queries that are used to perform write operations on data.
Root Query
Query or Mutation objects are basic GraphQL objects that do not have any associated data classes. In this case, the parser class will implement GraphQLQueryResolver or GraphQLMutationResolver. These resolvers will be searched for methods that map to fields in their respective root types.
Next, let’s define the root parser for Vehicle.
package com.techshard.graphql.query; import com.coxautodev.graphql.tools.GraphQLQueryResolver; import com.techshard.graphql.dao.entity.Vehicle; import com.techshard.graphql.service.VehicleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; import java.util.Optional; @Component public class VehicleQuery implements GraphQLQueryResolver { @Autowired private VehicleService vehicleService; public List<Vehicle> getVehicles(final int count) {return this.vehicleService.getAllVehicles(count);
}
public Optional<Vehicle> getVehicle(final int id) {
returnthis.vehicleService.getVehicle(id); }}Copy the code
In this class, we have methods to get a single Vehicle object and a list of Vehicle objects. Notice that we define these methods in the schema above.
Now, let’s define a Mutation parser.
package com.techshard.graphql.mutation;
import com.coxautodev.graphql.tools.GraphQLMutationResolver;
import com.techshard.graphql.dao.entity.Vehicle;
import com.techshard.graphql.service.VehicleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
@Component
public class VehicleMutation implements GraphQLMutationResolver {
@Autowired
private VehicleService vehicleService;
public Vehicle createVehicle(final String type, final String modelCode, final String brandName, final String launchDate) {
return this.vehicleService.createVehicle(type, modelCode, brandName, launchDate); }}Copy the code
In this class, we have only one method to create a Vehicle object, which corresponds to the Mutation type in our schema definition.
We will now define a service that can actually interact.
package com.techshard.graphql.service;
import com.techshard.graphql.dao.entity.Vehicle;
import com.techshard.graphql.dao.repository.VehicleRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
public class VehicleService {
private final VehicleRepository vehicleRepository ;
public VehicleService(final VehicleRepository vehicleRepository) {
this.vehicleRepository = vehicleRepository ;
}
@Transactional
public Vehicle createVehicle(final String type,final String modelCode, final String brandName, final String launchDate) {
final Vehicle vehicle = new Vehicle();
vehicle.setType(type);
vehicle.setModelCode(modelCode);
vehicle.setBrandName(brandName);
vehicle.setLaunchDate(LocalDate.parse(launchDate));
return this.vehicleRepository.save(vehicle);
}
@Transactional(readOnly = true)
public List<Vehicle> getAllVehicles(final int count) {
return this.vehicleRepository.findAll().stream().limit(count).collect(Collectors.toList());
}
@Transactional(readOnly = true)
public Optional<Vehicle> getVehicle(final int id) {
returnthis.vehicleRepository.findById(id); }}Copy the code
The test application
Now, we’re ready to test the application. Run the Spring Boot application. In the browser open HTTP / / localhost8080 graphiql links. We will see a friendly graphic meet, as shown below.
On the right side of the user interface, we can also see the document.
Now we can try running the following query.
mutation {
createVehicle(type: "car", modelCode: "XYZ0192", brandName: "XYZ", launchDate: "2016-08-16")
{
id
}
}
Copy the code
This creates a row of data in the Vehicle table. The result is:
{
"data": {
"createVehicle": {
"id": "1"}}}Copy the code
Now let’s run the query to get the data.
query {
vehicles(count: 1)
{
id,
type,
modelCode
}
}
Copy the code
And then we’ll get the result
{
"data": {
"vehicles": [{"id": "1"."type": "bus"."modelCode": "XYZ123"}}}]Copy the code
Note that we are only requesting a limited number of fields. We can change the query by adding or removing fields and see the new results.
conclusion
In this article, we explored the basic concepts of GraphQL. View detailed documentation.
The full source code for this tutorial can be found on GitHub.