Graphql for one to many relationship
The basics of graphql with spring boot has been explained in Graphql with springboot. The implementation of One to Many relationship in graphql spring boot project is explained here.
One to Many relationship in graphql:
- The one to Many relation between Author and Tutorial in the graphql schema will be
type Author {
id: ID!
name: String!
age: Int
}
type Tutorial {
id: ID!
title: String!
description: String
author: [Author]
}
The type Tutorial contains an author field which is a list of type Author in the same schema. This author field represents the One to Many relationship, i.e. One Tutorial and Many Author. The entity class for the Author will be
@Entity
@Table(name = "author")
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "age")
private Integer age;
//getters and setters
}
The entity class for Tutorial is
@Entity
@Table(name = "tutorial")
public class Tutorial {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "title", nullable = false)
private String title;
@Column(name = "description")
private String description;
@OneToMany
@JoinColumn(name = "author_id", nullable = false, updatable = false)
private List<Author> author;
//getters and setters
}
- Query type in graphql is used for querying. The query for finding all authors will be
type Query {
findAllAuthors: [Author]!
findAllTutorials: [Tutorial]!
oneAuthor(id :ID):Author
countAuthors: Long!
oneTutorial(id :ID):Tutorial
countTutorials: Long!
}
The corresponding Java method for this query which should be inside the Query class is
public Iterable<Author> findAllAuthors() {
return authorRepository.findAll();
}
public Optional<Author> oneAuthor(final Long id) {
return authorRepository.findById(id);
}
public Optional<Tutorial> oneTutorial(final Long id) {
return tutorialRepository.findById(id);
}
public Iterable<Tutorial> findAllTutorials() {
return tutorialRepository.findAll();
}
public long countAuthors() {
return authorRepository.count();
}
public long countTutorials() {
return tutorialRepository.count();
}
- Mutation type is used for creating and changing the data.The mutation type for author will be
type Mutation {
createAuthor(name: String!, age: Int): Author!
createTutorial(title: String!, description: String, author: ID!): Tutorial!
updateTutorial(id: ID!, title: String, description: String): Tutorial!
deleteTutorial(id: ID!): Boolean
}
the corresponding Java method for this mutation which should be inside the Mutation class is
public Author createAuthor(String name, Integer age) {
Author author = new Author();
author.setName(name);
author.setAge(age);
authorRepository.save(author);
return author;
}
public Tutorial createTutorial(String title, String description, Long authorId) {
Tutorial tutorilal = new Tutorial();
List<Author> l=tutorial.getAuthor();
l.add(new Author(authorId));
tutorial.setAuthor(l);
tutorial.setTitle(title);
tutorial.setDescription(description);
tutorialRepository.save(tutorial);
return tutorial;
}
public boolean deleteTutorial(Long id) {
tutorialRepository.deleteById(id);
return true;
}
public Tutorial updateTutorial(Long id, String title, String description) throws NotFoundException {
Optional<Tutorial> optTutorial = tutorialRepository.findById(id);
if (optTutorial.isPresent()) {
Tutorial tutorial = optTutorial.get();
if (title != null)
tutorial.setTitle(title);
if (description != null)
tutorial.setDescription(description);
tutorialRepository.save(tutorial);
return tutorial;
}
throw new NotFoundException("Not found Tutorial to update!");
}
Other than Mutation and Query class we will have tutorialResolver class which has a getAuthor method for a tutorial.
@Component
public class TutorialResolver implements GraphQLResolver<Tutorial> {
@Autowired
private AuthorRepository authorRepository;
public TutorialResolver(AuthorRepository authorRepository) {
this.authorRepository = authorRepository;
}
public List<Author> getAuthor(Tutorial tutorial) {
return (authorRepository.findAll());
}
}
Outputs:
- Graphql query in postman as a post method.
Find all:
For Author
query {
findAllAuthors{
id
name
age
}
}
and the result is
{
"data": {
"findAllAuthors": [
{
"id": "1",
"name": "ABC",
"age": 31
},
{
"id": "2",
"name": "DEF",
"age": 34
}
]
}
}
For tutorial
query {
findAllTutorials {
id
title
description
author {
id
name
age
}
}
}
and the result is
{
"data": {
"findAllTutorials": [
{
"id": "1",
"title": "JAVA",
"description": "JAVA BASIC",
"author": [
{
"id": "1",
"name": "ABC",
"age": 31
},
{
"id": "2",
"name": "DEF",
"age": 34
}
]
}
]
}
}
Here as it is One to many relationship there are two authors inside findAllTutorials for one tutorial.
Find One:
For Author
query {
oneAuthor(id:1) {
id
name
age
}
}
and the result is
{
"data": {
"oneAuthor": {
"id": "1",
"name": "ABC",
"age": 13
}
}
}
For tutorial
query {
oneTutorial(id:1) {
id
title
description
author {
name
id
}
}
}
and the result is
{
"data": {
"oneTutorial": {
"id": "1",
"title": "JAVA",
"description": "JSLKHJK",
"author": [
{
"name": "ABC",
"id": "1"
},
{
"name": "wsdfsw",
"id": "21"
}
]
}
}
}
Count:
For Author
query{
countAuthors
}
and the result is
{
"data": {
"countAuthors": 2
}
}
For tutorial
query{
countTutorials
}
and the result is
{
"data": {
"countTutorials": 2
}
}
- Graphql mutation in postman as a post method.
Update:
For tutorial
mutation {
updateTutorial(id:1,title:"JAX",description:"JAX ") {
title
id
description
}
}
and the result is
{
"data": {
"updateTutorial": {
"title": "JAX",
"id": "1",
"description": "JAX "
}
}
}
Written by Aravind P C