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.