version: '3'
services:
mysql:
image: registry.cn-hangzhou.aliyuncs.com/zhengqing/mysql:5.7
container_name: mysql_3306
restart: unless-stopped
volumes:
- "./mysql/my.cnf:/etc/mysql/my.cnf"
- "./mysql/init-file.sql:/etc/mysql/init-file.sql"
- "./mysql/data:/var/lib/mysql"
# - "./mysql/conf.d:/etc/mysql/conf.d"
- "./mysql/log/mysql/error.log:/var/log/mysql/error.log"
- "./mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d" # init sql script directory -- tips: it can be excute when `/var/lib/mysql` is empty
environment: # set environment,equals docker run -e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
MYSQL_ROOT_PASSWORD: root # set root password
MYSQL_DATABASE: demo # init database name
ports: # port mappping
- "3306:3306"
运行
docker-compose -f docker-compose.yml -p mysql5.7 up -d
初始化脚本
CREATE DATABASE IF NOT EXISTS `BOOK_API_DATA`; USE `BOOK_API_DATA`; CREATE TABLE IF NOT EXISTS `Book` ( `id` int(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `pageCount` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `Index_name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=235 DEFAULT CHARSET=utf8; CREATE TABLE `Author` ( `id` INT(20) NOT NULL AUTO_INCREMENT, `firstName` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_general_ci', `lastName` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_general_ci', `bookId` INT(20) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `Index_name` (`firstName`) USING BTREE, INDEX `FK_Author_Book` (`bookId`) USING BTREE, CONSTRAINT `FK_Author_Book` FOREIGN KEY (`bookId`) REFERENCES `BOOK_API_DATA`.`Book` (`id`) ON UPDATE CASCADE ON DELETE CASCADE ) COLLATE='utf8_general_ci' ENGINE=InnoDB AUTO_INCREMENT=6 ; INSERT INTO `Book` (`id`, `name`, `pageCount`) VALUES (1, 'the golden ticket', '255'); INSERT INTO `Book` (`id`, `name`, `pageCount`) VALUES (2, 'coding game', '300'); INSERT INTO `Author` (`id`, `firstName`, `LastName`, `bookId`) VALUES (4, 'Brendon', 'Bouchard', 1); INSERT INTO `Author` (`id`, `firstName`, `LastName`, `bookId`) VALUES (5, 'John', 'Doe', 2);
1. 定义Schema,Schema使用GraphQL Schema Definition Language (SDL)来定义
2. 实现Resolver,Resolver函数负责从数据源中获取请求的数据
3. 配置和启动GraphQL服务器 ,要启动GraphQL服务器,你需要安装相应的依赖和配置服务器
<?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">
<parent>
<artifactId>springboot-demo</artifactId>
<groupId>com.et</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>GraphQL</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<kotlin.version>1.5.0</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>12.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>12.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>26.0-jre</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
package com.et.graphql.queryresolvers;
import com.et.graphql.model.Author;
import com.et.graphql.model.Book;
import com.et.graphql.repository.AuthorRepository;
import com.et.graphql.repository.BookRepository;
import graphql.kickstart.tools.GraphQLQueryResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BookQuery implements GraphQLQueryResolver{
@Autowired
BookRepository bookRepository;
@Autowired
AuthorRepository authorRepository;
public Iterable<Book> allBook(){
return bookRepository.findAll();
}
public Book getBookByName(String name){
return bookRepository.findBookByName(name);
}
public Iterable<Author> allAuthor(){
return authorRepository.findAll();
}
}
package com.et.graphql.queryresolvers;
import com.et.graphql.model.Book;
import com.et.graphql.repository.BookRepository;
import graphql.kickstart.tools.GraphQLMutationResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class BookMutation implements GraphQLMutationResolver {
@Autowired
BookRepository bookRepository;
public Book newBook(String name, String pageCount){
Book book = new Book();
book.setName(name);
book.setPageCount(pageCount);
return bookRepository.save(book);
}
public Book deleteBook(Integer id){
Book deleteBook = new Book();
Optional<Book> findBook = bookRepository.findById(id);
if(findBook.isPresent()){
bookRepository.delete(findBook.get());
deleteBook = findBook.get();
}
return deleteBook;
}
}
package com.et.graphql.queryresolvers;
import com.et.graphql.model.Author;
import com.et.graphql.model.Book;
import com.et.graphql.repository.AuthorRepository;
import graphql.kickstart.tools.GraphQLResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BookAuthorResolver implements GraphQLResolver<Book> {
@Autowired
AuthorRepository authorRepository;
public Author getAuthor(Book book){
return authorRepository.findAuthorByBookId(book.getId());
}
}
graphqls(/resources/graphql)
type Book {
id: Int
name: String
pageCount: String
author: Author
}
type Query {
allBook: [Book]
allAuthor:[Author]
getBookByName(name: String): Book
}
type Mutation {
newBook(name: String!, pageCount: String): Book
deleteBook(id:Int!):Book
}
type Author {
id: Int
firstName: String
lastName: String
bookId: Int
}
package com.et.graphql.model;
import javax.persistence.*;
@Entity
@Table(name = "Author", schema = "BOOK_API_DATA")
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Integer id;
@Column(name = "firstname")
String firstName;
@Column(name = "lastname")
String lastName;
@Column(name = "bookid")
Integer bookId;
public Author(Integer id, String firstName, String lastName, Integer bookId) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.bookId = bookId;
}
public Author() {
}
public Integer getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public void setId(Integer id) {
this.id = id;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getBookId() {
return bookId;
}
public void setBookId(Integer bookId) {
this.bookId = bookId;
}
}
package com.et.graphql.model;
import javax.persistence.*;
@Entity
@Table(name = "Book", schema = "BOOK_API_DATA")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
@Column(name = "pagecount")
private String pageCount;
public Book(Integer id, String name, String pageCount) {
this.id = id;
this.name = name;
this.pageCount = pageCount;
}
public Book() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPageCount() {
return pageCount;
}
public void setPageCount(String pageCount) {
this.pageCount = pageCount;
}
}
package com.et.graphql.repository;
import com.et.graphql.model.Author;
import org.springframework.data.repository.CrudRepository;
public interface AuthorRepository extends CrudRepository<Author, Integer> {
Author findAuthorByBookId(Integer bookId);
}
package com.et.graphql.repository;
import com.et.graphql.model.Book;
import org.springframework.data.repository.CrudRepository;
public interface BookRepository extends CrudRepository<Book, Integer> {
Book findBookByName(String name);
}
package com.et.graphql;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackages = "com.et.graphql.queryresolvers")
public class BookAPIApplication {
public static void main(String[] args) {
SpringApplication.run(BookAPIApplication.class, args);
}
}
spring.jpa.hibernate.ddl-auto=none
spring.jpa.database=mysql
spring.jpa.open-in-view=true
spring.jpa.show-sql=true
server.port=8088
#logging.level.org.hibernate=DEBUG
logging.level.org.hibernate.SQL=DEBUG
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.use-new-id-generator-mappings= false
# book api db"
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
query {
allBook{
id
name
pageCount
}
}