{"id":16534627,"url":"https://github.com/hardyscc/java-graphql-sample","last_synced_at":"2026-04-18T17:03:16.265Z","repository":{"id":103774594,"uuid":"282783384","full_name":"hardyscc/java-graphql-sample","owner":"hardyscc","description":"Build a basic CRUD backend application in Java Spring Boot with GraphQL \u0026 MySQL.","archived":false,"fork":false,"pushed_at":"2022-03-02T02:54:17.000Z","size":69,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-27T05:59:59.726Z","etag":null,"topics":["graphql","graphql-java","graphql-java-kickstart","graphql-spqr","java","lombok","mybatis-migrations","mysql","spring-boot","spring-doc"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hardyscc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-27T03:18:27.000Z","updated_at":"2024-09-16T19:58:31.000Z","dependencies_parsed_at":null,"dependency_job_id":"ac50d728-1f27-4a00-b6ef-83959fe24036","html_url":"https://github.com/hardyscc/java-graphql-sample","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hardyscc/java-graphql-sample","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hardyscc%2Fjava-graphql-sample","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hardyscc%2Fjava-graphql-sample/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hardyscc%2Fjava-graphql-sample/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hardyscc%2Fjava-graphql-sample/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hardyscc","download_url":"https://codeload.github.com/hardyscc/java-graphql-sample/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hardyscc%2Fjava-graphql-sample/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31976806,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T16:27:12.723Z","status":"ssl_error","status_checked_at":"2026-04-18T16:27:11.140Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphql","graphql-java","graphql-java-kickstart","graphql-spqr","java","lombok","mybatis-migrations","mysql","spring-boot","spring-doc"],"created_at":"2024-10-11T18:24:49.343Z","updated_at":"2026-04-18T17:03:16.247Z","avatar_url":"https://github.com/hardyscc.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Java GraphQL Backend Tutorial\n\n## Overview\n\nBuild a basic CRUD backend application in Java Spring Boot with GraphQL \u0026 MySQL.\n\n## Technologies\n\n1. [Java](https://www.oracle.com/java/)\n2. [Spring Boot](https://spring.io/projects/spring-boot)\n3. [Maven](https://maven.apache.org/)\n4. [GraphQL Spring Framework Boot Starters](https://github.com/graphql-java-kickstart/graphql-spring-boot)\n5. [MySQL](https://www.mysql.com/)\n6. [MyBatis Migrations](http://mybatis.org/migrations/)\n\n## Create an Empty Project\n\n### Download the template of an Empty Project\n\nSetup an empty project using [Spring Initializr](https://start.spring.io/).\n\n1. Update the field \"Artifact\" as `java-graphql-sample`.\n\n2. Update the field \"Package name\" as `com.example.jgs`.\n\n3. Press `ADD DEPENDENCIES...` button to add the following dependency: `Spring Web`.\n\n\u003e Please use Maven Project in Java 8, packaging as JAR for this tutorial.\n\nPress the `GENERATE` button to download an empty project template.\nExtract the zip folder to start editing.\n\n### Add a Default Controller\n\nCreate the following file `src/main/java/com/example/jgs/controller/HealthController.java`.\n\n```java\npackage com.example.jgs.controller;\n\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class HealthController {\n\n    @GetMapping\n    public String check() {\n        return \"OK\";\n    }\n}\n```\n\nStart server with below command:\n\n```bash\nmvnw spring-boot:run\n```\n\nGoto http://localhost:8080 You should see the `OK` message.\n\n## Add GraphQL Dependencies\n\n### Add JPA and GraphQL dependency\n\nUpdate the `pom.xml` as follow.\n\n```xml\n    \u003cproperties\u003e\n        ...\n        \u003cgraphql-java-kickstart.version\u003e7.1.0\u003c/graphql-java-kickstart.version\u003e\n        \u003cgraphql-spqr.version\u003e0.10.1\u003c/graphql-spqr.version\u003e\n    \u003c/properties\u003e\n\n    \u003cdependencies\u003e\n        ...\n        \u003cdependency\u003e\n            \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n            \u003cartifactId\u003espring-boot-starter-data-jpa\u003c/artifactId\u003e\n        \u003c/dependency\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003ecom.graphql-java-kickstart\u003c/groupId\u003e\n            \u003cartifactId\u003egraphql-spring-boot-starter\u003c/artifactId\u003e\n            \u003cversion\u003e${graphql-java-kickstart.version}\u003c/version\u003e\n            \u003cexclusions\u003e\n                \u003cexclusion\u003e\n                    \u003cgroupId\u003ecom.graphql-java\u003c/groupId\u003e\n                    \u003cartifactId\u003egraphql-java\u003c/artifactId\u003e\n                \u003c/exclusion\u003e\n            \u003c/exclusions\u003e\n        \u003c/dependency\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003ecom.graphql-java-kickstart\u003c/groupId\u003e\n            \u003cartifactId\u003eplayground-spring-boot-starter\u003c/artifactId\u003e\n            \u003cversion\u003e${graphql-java-kickstart.version}\u003c/version\u003e\n            \u003cscope\u003eruntime\u003c/scope\u003e\n        \u003c/dependency\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003eio.leangen.graphql\u003c/groupId\u003e\n            \u003cartifactId\u003espqr\u003c/artifactId\u003e\n            \u003cversion\u003e${graphql-spqr.version}\u003c/version\u003e\n        \u003c/dependency\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003ecom.h2database\u003c/groupId\u003e\n            \u003cartifactId\u003eh2\u003c/artifactId\u003e\n            \u003cscope\u003eruntime\u003c/scope\u003e\n        \u003c/dependency\u003e\n    \u003c/dependencies\u003e\n...\n```\n\n### Create the User Entity and Service\n\nCreate the following file `src/main/java/com/example/jgs/input/CreateUser.java`.\n\n```java\npackage com.example.jgs.input;\n\nimport io.leangen.graphql.annotations.GraphQLNonNull;\nimport lombok.Data;\n\n@Data\npublic class CreateUser {\n    @GraphQLNonNull\n    private String name;\n\n    private String nickName;\n}\n```\n\nCreate the following file `src/main/java/com/example/jgs/model/User.java`.\n\n```java\npackage com.example.jgs.model;\n\nimport com.example.jgs.input.CreateUser;\nimport io.leangen.graphql.annotations.GraphQLNonNull;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\nimport org.hibernate.annotations.Type;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport java.util.UUID;\n\n@Entity\n@Data\n@Builder\n@AllArgsConstructor\n@NoArgsConstructor\npublic class User {\n\n    @Id\n    @GeneratedValue\n    @Type(type = \"uuid-char\")\n    @GraphQLNonNull\n    @Column(length = 36)\n    private UUID id;\n\n    @GraphQLNonNull\n    private String name;\n\n    private String nickName;\n\n    public static User from(CreateUser createUser) {\n        return User.builder().name(createUser.getName())\n                .nickName(createUser.getNickName())\n                .build();\n    }\n}\n```\n\nCreate the following file `src/main/java/com/example/jgs/repository/UserRepository.java`.\n\n```java\npackage com.example.jgs.repository;\n\nimport com.example.jgs.model.User;\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.UUID;\n\n@Repository\npublic interface UserRepository extends JpaRepository\u003cUser, UUID\u003e {\n}\n```\n\nCreate the following file `src/main/java/com/example/jgs/service/UserService.java`.\n\n```java\npackage com.example.jgs.service;\n\nimport com.example.jgs.input.CreateUser;\nimport com.example.jgs.model.User;\nimport com.example.jgs.repository.UserRepository;\nimport lombok.AllArgsConstructor;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.UUID;\n\n@Service\n@AllArgsConstructor\npublic class UserService {\n\n    private final UserRepository userRepository;\n\n    public List\u003cUser\u003e find() {\n        return this.userRepository.findAll();\n    }\n\n    public User findOneById(UUID id) {\n        return this.userRepository.findById(id).orElse(null);\n    }\n\n    public User create(CreateUser createUser) {\n        return this.userRepository.save(User.from(createUser));\n    }\n\n    public boolean delete(UUID id) {\n        if (this.userRepository.existsById(id)) {\n            this.userRepository.deleteById(id);\n            return true;\n        }\n        return false;\n    }\n}\n```\n\n### Implement the User Resolver\n\nCreate the following file `src/main/java/com/example/jgs/resolver/UserResolver.java`.\n\n```java\npackage com.example.jgs.resolver;\n\nimport com.example.jgs.input.CreateUser;\nimport com.example.jgs.model.User;\nimport com.example.jgs.service.UserService;\nimport io.leangen.graphql.annotations.GraphQLArgument;\nimport io.leangen.graphql.annotations.GraphQLMutation;\nimport io.leangen.graphql.annotations.GraphQLNonNull;\nimport io.leangen.graphql.annotations.GraphQLQuery;\nimport lombok.AllArgsConstructor;\nimport org.springframework.stereotype.Controller;\n\nimport java.util.List;\nimport java.util.UUID;\n\n@Controller\n@AllArgsConstructor\npublic class UserResolver {\n\n    private final UserService userService;\n\n    @GraphQLQuery\n    @GraphQLNonNull\n    public List\u003c@GraphQLNonNull User\u003e users() {\n        return this.userService.find();\n    }\n\n    @GraphQLQuery\n    public User user(\n            @GraphQLArgument(name = \"id\") UUID id) {\n        return this.userService.findOneById(id);\n    }\n\n    @GraphQLMutation\n    @GraphQLNonNull\n    public User createUser(\n            @GraphQLArgument(name = \"input\") @GraphQLNonNull CreateUser createUser) {\n        return this.userService.create(createUser);\n    }\n\n    @GraphQLMutation\n    public UUID deleteUser(\n            @GraphQLArgument(name = \"id\") UUID id) {\n        return this.userService.delete(id) ? id : null;\n    }\n}\n```\n\n### Add Config for GraphQL\n\nCreate the following file `src/main/java/com/example/jgs/config/GraphqlConfig.java`.\n\n```java\npackage com.example.jgs.config;\n\nimport com.example.jgs.resolver.UserResolver;\nimport graphql.schema.GraphQLSchema;\nimport io.leangen.graphql.GraphQLSchemaGenerator;\nimport lombok.AllArgsConstructor;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n@Configuration\n@AllArgsConstructor\npublic class GraphqlConfig {\n\n    private final UserResolver userResolver;\n\n    @Bean\n    GraphQLSchema schema() {\n        return new GraphQLSchemaGenerator()\n                .withBasePackages(\"com.example.jgs\")\n                .withOperationsFromSingleton(this.userResolver)\n                .generate();\n    }\n}\n```\n\nRename `src/main/resources/application.properties` to `src/main/resources/application.yml`. Then Add the following:\n\n```yml\nspring:\n  datasource:\n    url: jdbc:h2:mem:testdb\n```\n\n### Test the GraphQL Endpoint\n\nStart the server.\n\n```bash\nmvnw spring-boot:run\n```\n\nGoto the GraphQL Playground - http://localhost:8080/playground.\n\n1. Create a new user\n\n   ```graphql\n   mutation {\n     createUser(input: { name: \"Tommy\" }) {\n       id\n     }\n   }\n   ```\n\n   Output :\n\n   ```json\n   {\n     \"data\": {\n       \"createUser\": {\n         \"id\": \"8ec8105e-1ffc-4fe3-81fb-882b3dd33f82\"\n       }\n     }\n   }\n   ```\n\n2. Query the users\n\n   ```graphql\n   query {\n     users {\n       id\n       name\n     }\n   }\n   ```\n\n   Output :\n\n   ```json\n   {\n     \"data\": {\n       \"users\": [\n         {\n           \"id\": \"8ec8105e-1ffc-4fe3-81fb-882b3dd33f82\",\n           \"name\": \"Tommy\"\n         }\n       ]\n     }\n   }\n   ```\n\n## Setup DB and DB migration\n\n### Config MySQL and MyBatis Migrations\n\nUpdate the following file `pom.xml`\n\n```xml\n...\n    \u003cproperties\u003e\n        ...\n        \u003cmybatis-migrations-autoconfigure.version\u003e0.0.2\u003c/mybatis-migrations-autoconfigure.version\u003e\n    \u003c/properties\u003e\n\n    \u003cdependencies\u003e\n        ...\n        \u003cdependency\u003e\n            \u003cgroupId\u003emysql\u003c/groupId\u003e\n            \u003cartifactId\u003emysql-connector-java\u003c/artifactId\u003e\n            \u003cscope\u003eruntime\u003c/scope\u003e\n        \u003c/dependency\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003ede.bessonov\u003c/groupId\u003e\n            \u003cartifactId\u003emybatis-migrations-spring-boot-autoconfigure\u003c/artifactId\u003e\n            \u003cversion\u003e${mybatis-migrations-autoconfigure.version}\u003c/version\u003e\n        \u003c/dependency\u003e\n    \u003c/dependencies\u003e\n...\n```\n\nUpdate the following file `src/main/resources/application.yml`.\n\n```yml\nspring:\n  datasource:\n    url: jdbc:${DATABASE_URL:mysql://usr:User12345@localhost:3306/development}\n\nlogging:\n  level:\n    org.hibernate.SQL: DEBUG\n    org.hibernate.type.descriptor.sql.BasicBinder: TRACE\n\nserver:\n  port: 4000\n```\n\n### Initialize the migration scripts\n\nCreate a folder `scripts` under `src/main/resources`\n\nCreate the following file `src/main/resources/scripts/\u003cyyyymmddHHmmss\u003e_create_changelog.sql` \u003c/br\u003e (e.g. 20200728095409_create_changelog.sql )\n\n```sql\n-- // Create Changelog\n\n-- Default DDL for changelog table that will keep\n-- a record of the migrations that have been run.\n\n-- You can modify this to suit your database before\n-- running your first migration.\n\n-- Be sure that ID and DESCRIPTION fields exist in\n-- BigInteger and String compatible fields respectively.\n\nCREATE TABLE ${changelog} (\n  ID NUMERIC(20,0) NOT NULL,\n  APPLIED_AT VARCHAR(25) NOT NULL,\n  DESCRIPTION VARCHAR(255) NOT NULL,\n  PRIMARY KEY(ID)\n);\n\n-- //@UNDO\nDROP TABLE ${changelog};\n```\n\nCreate the following file `src/main/resources/scripts/\u003cyyyymmddHHmmss\u003e_first_migration.sql` \u003c/br\u003e (e.g. 20200728095410_first_migration.sql )\n\n```sql\n-- // First migration.\n-- Migration SQL that makes the change goes here.\nCREATE TABLE user (\n  id VARCHAR(36) NOT NULL,\n  name VARCHAR(255) NOT NULL,\n  nick_name VARCHAR(255) NULL,\n  PRIMARY KEY(id)\n);\n\n-- //@UNDO\n-- SQL to undo the change goes here.\nDROP TABLE user;\n```\n\n\u003e Please note the following points when creating new script: \u003cbr /\u003e 1. The naming convention is `\u003cyyyymmddHHmmss\u003e_\u003cdescription\u003e.sql` \u003cbr /\u003e 2. Put undo SQL under `-- //@UNDO` section.\n\n### Test the migration script\n\n#### Build the jar\n\nCreate the following file `src/test/resources/application.yml`.\n\n```yml\nspring:\n  datasource:\n    url: jdbc:h2:mem:testdb\n\ngraphql:\n  servlet:\n    websocket:\n      enabled: false\n```\n\nUpdate the dependency of `com.h2database` in `pom.xml` as follow:\n\n```xml\n...\n\t\t\u003cdependency\u003e\n\t\t\t\u003cgroupId\u003ecom.h2database\u003c/groupId\u003e\n\t\t\t\u003cartifactId\u003eh2\u003c/artifactId\u003e\n\t\t\t\u003cscope\u003etest\u003c/scope\u003e\n\t\t\u003c/dependency\u003e\n...\n```\n\nPackage the jar by command:\n\n```bash\nmvnw package\n```\n\n#### Execution of migration command\n\nStart a MySQL docker instance.\n\n```bash\ndocker run -d -e \"MYSQL_ROOT_PASSWORD=Admin12345\" -e \"MYSQL_USER=usr\" -e \"MYSQL_PASSWORD=User12345\" -e \"MYSQL_DATABASE=development\" -p 3306:3306 --name some-mysql bitnami/mysql:5.7.27\n```\n\nRun the below command and look at migration status before executing the scripts:\n\n```bash\n\u003ejava -jar target/java-graphql-sample-0.0.1-SNAPSHOT.jar migrations status\n\nID             Applied At          Description\n================================================================================\n20200812020020    ...pending...    create changelog\n20200812020021    ...pending...    first migration\n```\n\nExecution of the migration script:\n\n```bash\njava -jar target/java-graphql-sample-0.0.1-SNAPSHOT.jar migrations up\n```\n\nRun the below command again to check the applied time:\n\n```bash\n\u003ejava -jar target/java-graphql-sample-0.0.1-SNAPSHOT.jar migrations status\n\nID             Applied At          Description\n================================================================================\n20200812020020 2020-08-12 11:43:46 create changelog\n20200812020021 2020-08-12 11:43:46 first migration\n```\n\n### Test the GraphQL Endpoint\n\nStart the server.\n\n```bash\nmvnw spring-boot:run\n```\n\nGoto the GraphQL Playground - http://localhost:4000/playground.\n\n1. Create some users\n\n   ```graphql\n   mutation {\n     a: createUser(input: { name: \"John\" }) {\n       id\n     }\n     b: createUser(input: { name: \"Mary\" }) {\n       id\n     }\n   }\n   ```\n\n   Output:\n\n   ```json\n   {\n     \"data\": {\n       \"a\": {\n         \"id\": \"94ae9dd3-c739-4c04-8bfb-6a7c94552cd6\"\n       },\n       \"b\": {\n         \"id\": \"2aa8e496-0c9d-41b4-a0c8-467beaf14247\"\n       }\n     }\n   }\n   ```\n\n2. Query the users\n\n   ```graphql\n   query {\n     users {\n       id\n       name\n     }\n   }\n   ```\n\n   Output :\n\n   ```json\n   {\n     \"data\": {\n       \"users\": [\n         {\n           \"id\": \"2aa8e496-0c9d-41b4-a0c8-467beaf14247\",\n           \"name\": \"Mary\"\n         },\n         {\n           \"id\": \"94ae9dd3-c739-4c04-8bfb-6a7c94552cd6\",\n           \"name\": \"John\"\n         }\n       ]\n     }\n   }\n   ```\n\n3. Delete one of the user by the id\n\n   ```graphql\n   mutation {\n     deleteUser(id: \"94ae9dd3-c739-4c04-8bfb-6a7c94552cd6\")\n   }\n   ```\n\n   Output :\n\n   ```json\n   {\n     \"data\": {\n       \"deleteUser\": \"94ae9dd3-c739-4c04-8bfb-6a7c94552cd6\"\n     }\n   }\n   ```\n\n4. Test the MySQL database\n\n   Run the mysql command using the same docker instance.\n\n   ```bash\n   docker exec -it some-mysql mysql -uroot -p\"Admin12345\"\n   ```\n\n   Select the data from user table.\n\n   ```sql\n   mysql\u003e use development;\n   mysql\u003e select * from user;\n   +--------------------------------------+------+----------+\n   | id                                   | name | nickName |\n   +--------------------------------------+------+----------+\n   | 2aa8e496-0c9d-41b4-a0c8-467beaf14247 | Mary | NULL     |\n   +--------------------------------------+------+----------+\n   ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhardyscc%2Fjava-graphql-sample","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhardyscc%2Fjava-graphql-sample","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhardyscc%2Fjava-graphql-sample/lists"}