grahql操作

 

 一次查询可以查询多次数据,先查询当前here的id,得到id之后,再去查向这个人的朋友

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 查询电影jedi和EMPIRE中英雄的名字

但是上面查询的的时候存在hero这个字段命名冲突的问题,我们可以给字段设置别名

 

 我们也可以给name字段重命名

 

 

 

 给query设置名字

 

 我们查询某部电影里面hero英雄的名字和英雄朋友的信息,这里要传入电影的名称,我们定义了一个变量,变量以$开始,:是变量的类型这里是一个枚举类型

 

 

 

 

 

 

 

 !表示这个变量必须存在,=是变量的默认值

我们修改数据用的是下面的结构

 

 修改对象使用的是mutation关键字,修改对象的名字是createReview,函数里面需要提交两个参数一个是episode,一个是revied对象

创建之后函数createReview会有一个返回对象,对象中包含了episode和stras两个值

我们来看下查询hreo的定义

 

 hero查询需要输入一个参数episode,参数的类型是一个枚举的Episode,hero查询的返回值是Character类型

Character是一个接口类型

 

 human实现了Character这个接口类型

 

 

 

 所以我们在查询的时候,一定要注意,human实现了Character的接口,human中就包含了chaaacter的所有字段,此外human还可以单独定义其他字段如appearsIl这个这段

因为hero查询默认是Character类型,所以字段必须是Character,如果要查询appearsIn,需要使用下面的形式

 

 接下来我们看下面的search函数

 

 参数是一个text类型,返回值是SearchResult是一个枚举类型,查询我们可以使用下面的方法

 

 

 

 接下来看看schema

 

 

 在shema中定义了一个hello的查询方法,方法的返回值是string类型

方法的resolver在root中定义

 

 

 

 上面查询的hello和accountName方法返回值都是一个字符串类型,如果要返回一个自定义的类型,如何实现了

 

 方法account返回值就是一个自定义的类型Account,我们需要在schema中进行定义

我们在resolver中定义如下

 

 查询如下

 

 

 

 

 

 我们来看下下面的这个案例

 

 

 

 

 

 我们在shema中进行定义

 

 resolver中进行实现

 

 

 

 

 

 这个视频超级经典呀

https://blog.csdn.net/gaoyib6/article/details/76088903?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

 

我们来看下我们的案例及其使用的效果图

 

 

 

 

 

 

 

 删除书籍

 

 

 

 插入作者

 

 

 

 

 

 别名的使用

 

 

2.片段

片段使你能够组织一组字段,然后在需要它们的的地方引入

 

 

3.操作名称

操作类型可以是 querymutation 或 subscription,描述你打算做什么类型的操作。操作类型是必需的,除非你使用查询简写语法,在这种情况下,你无法为操作提供名称或变量定义。

操作名称是你的操作的有意义和明确的名称。它仅在有多个操作的文档中是必需的,但我们鼓励使用它,因为它对于调试和服务器端日志记录非常有用。

下面的示例包含了作为操作类型的关键字 query 以及操作名称 getAuhtor:

上面的查询默认我们没有写操作类型,但是我们最好按照下面的方式来编写

 

 

4.变量

所有声明的变量都必须是标量、枚举型或者输入对象类型。所以如果想要传递一个复杂对象到一个字段上,你必须知道服务器上其匹配的类型。可以从Schema页面了解更多关于输入对象类型的信息。

 

对于输入的变量我们也可以设置默认值

 

 

5.指令

一个指令可以附着在字段或者片段包含的字段上,然后以任何服务端期待的方式来改变查询的执行。GraphQL 的核心规范包含两个指令,其必须被任何规范兼容的 GraphQL 服务器实现所支持:

  • @include(if: Boolean) 仅在参数为 true 时,包含此字段。
  • @skip(if: Boolean) 如果参数为 true,跳过此字段。

指令在你不得不通过字符串操作来增减查询的字段时解救你。服务端实现也可以定义新的指令来添加新的特性。

我们来看下面的案例

 

 

指令在你不得不通过字符串操作来增减查询的字段时解救你。服务端实现也可以定义新的指令来添加新的特性。

6枚举类型

枚举类型是一种特殊的标量,它限制在一个特殊的可选值集合内。这让你能够:

  1. 验证这个类型的任何参数是可选值的的某一个
  2. 与类型系统沟通,一个字段总是一个有限值集合的其中一个值。

建立一个枚举类:

 

 

接下来我们来看看我们的代码

springboot集成grahqp:代码仓库的地址位于https://gitee.com/kebibuluan/springboot-grahql

本代码转载自:https://my.oschina.net/hanchao/blog/3014116

https://github.com/windhan2100/graphql

https://www.cnblogs.com/dionysun/p/12130440.html

https://blog.csdn.net/weixin_34356555/article/details/91893706

相当的经典呀

在spring-boot中使用graphql

参照graphql-java-kick-to-start

首先构建spring-boot项目,pom.xml文件中加入

<dependency>
  <groupId>com.graphql-java-kickstart</groupId>
  <artifactId>graphql-java-tools</artifactId>
  <version>5.4.0</version>
</dependency>
<!-- graphql -->
<dependency>
   <groupId>com.graphql-java</groupId>
   <artifactId>graphql-spring-boot-starter</artifactId>
   <version>5.0.2</version>
</dependency>
<!-- 这个是graphiql,跟上面的不一样 -->
 <dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphiql-spring-boot-starter</artifactId>
    <version>5.0.2</version>
</dependency>

接着定义graphql的schema,在resources目录下任意位置的*.graphqls文件都会被扫描到,作为graphql 的schema。

这里在resources下先建一个文件夹/graphql,建立schema文件

 

 

root.graphqls

#查询入口
type Query {
    ####### Author相关 #########
    findAuthorById(id:Long!): Author
 
    findAllAuthors: [Author]!
 
    countAuthors: Long!
 
    ####### Book相关 #########
    findAllBooks: [Book]!
    countBooks: Long!
}
 
type Mutation {
    newAuthor(firstName: String!,lastName: String!) : Author!
 
    newBook(title: String!,isbn: String!,pageCount: Int, authorId: Long!) : Book!
    saveBook(input: BookInput!) : Book!
    deleteBook(id: ID!) : Boolean
    updateBookPageCount(pageCount: Int!, id:Long!) : Book!
}

schema.graphqls

type Author {
    #作者Id
    id: Long!
    #创建时间
    createdTime: String
    #名
    firstName: String
    #姓
    lastName: String
    #该作者的所有书籍
    books: [Book]
}
 
input BookInput {
    title: String!
    isbn: String!
    pageCount: Int
    authorId: Long
}
 
type Book {
    id: Long!
    title: String!
    isbn: String!
    pageCount: Int
    author: Author
}

GraphQL Java Tools可以将schema中定义的类型的属性与java对象的属性或方法对应起来。即上面的User类型,可以使用一个类与之对应

列如schema.graphqls中定义了一个Book类

type Book {
    id: Long!
    title: String!
    isbn: String!
    pageCount: Int
    author: Author
}

GraphQL Java Tools可以将schema中定义的类型的属性与java对象的属性或方法对应起来

package com.hanchao.graphql.graphql.entity;

import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.persistence.Column;
import javax.persistence.Entity;


@Entity
@Data
@EqualsAndHashCode(callSuper = false)
public class Book extends BaseEntity {
    @Column(columnDefinition = "varchar(50)")
    private String title;

    private String isbn;

    private int pageCount;

    private long authorId;

    private Double price;
}

这里我们一定要注意,GraphQL Java Tools可以将schema中定义的类型的属性与java对象的属性或方法对应起来,映射的规则如下

Type Query 没有对应的java class,如果type 中的所有字段和java class成员变量一致,则该type可以不用定义Resolver.

graphql type中的字段映射Java class字段的优先级

对于graphql objectType中的字段映射为java class字段顺序如下:

method (*fieldArgs [, DataFetchingEnvironment])
method is(*fieldArgs [, DataFetchingEnvironment]), only if the field returns a Boolean
method get(*fieldArgs [, DataFetchingEnvironment])
method getField(*fieldArgs [, DataFetchingEnvironment])
field
例如:

上述type Book中的name字段的映射顺序为:

在java Book类中找name(参数)方法。
如果Book类中没有name(参数)方法,则继续找isName(参数)方法。
如果Book中没有isName(参数)方法,则继续在Book中找getName(参数)方法。
如果Book中没有getName()方法,则继续在Book中找getFieldName(参数)方法。
如果Book中没有getFieldName(参数)方法,在继续在Book中找name成员变量。
如果Book中没有name成员变量,则报错。
graphql type中的字段映射Resolver的优先级:

method (dataClassInstance, *fieldArgs [, DataFetchingEnvironment])
method is(dataClassInstance, *fieldArgs [, DataFetchingEnvironment]), only if the field returns a Boolean
method get(dataClassInstance, *fieldArgs [, DataFetchingEnvironment])
method getField(dataClassInstance, *fieldArgs [, DataFetchingEnvironment])
注:Resolver的映射优先级高于Java Class,首先在Resolver中查找,如果没找到,才会在Java class中查找 :例如上述type Book中的author字段,会首先映射为BookResolver重的author(Book)方法。

type Book {
id: Long!
title: String!
isbn: String!
pageCount: Int
author: Author
}

type Book 中定义的id字段与Book类中name属性为id的一一对应

但是在type Book 中定义的author字段,在Book类中没有对应的字段与之对于,这个时候就要使用Resolver来解决这个问题

package com.hanchao.graphql.graphql.resolver;

import com.coxautodev.graphql.tools.GraphQLResolver;
import com.hanchao.graphql.graphql.entity.Author;
import com.hanchao.graphql.graphql.entity.Book;
import com.hanchao.graphql.graphql.enums.CountryEnum;
import com.hanchao.graphql.graphql.repo.AuthorRepo;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;


/**
 * @author hanliwei
 * @create 2019-02-12 17:36
 */
@Component
@AllArgsConstructor
public class BookResolver implements GraphQLResolver<Book> {

    private AuthorRepo authorRepo;

    public Author getAuthor(Book book) {
        return authorRepo.findAuthorById(book.getAuthorId());
    }

    public String getMoney(Book book,CountryEnum country) {
        if (country == CountryEnum.CHINA) {
            return "¥:" + book.getPrice() * 6;
        } else if (country == CountryEnum.USA) {
            return "$:" + book.getPrice();
        } else {
            return "free";
        }
    }
}

项目启动的时候会查询BookResolver,发现method getField(dataClassInstance, *fieldArgs [, DataFetchingEnvironment]) 

getAuthor(Book book)就是安装上面的方式定义的,就会将author: Author与对应的java 的实体类关联起来

type Book {
id: Long!
title: String!
isbn: String!
pageCount: Int
author: Author
}

那么到底type Article {...}schema里面的属性怎么解析呢?是与数据类进行映射,还是与resolver中的方法进行映射?

官网上给出了映射的优先级:

首先是resolver

  1. method 属性名(...)
  2. method is属性名(...)
  3. method get属性名(...)
  4. method getField属性名(...)

其次是Data Class(即与类型对应的java类)

  1. method 属性名(...)
  2. method is属性名(...)
  3. method get属性名(...)
  4. method getField属性名(...)
  5. field 属性名

所以首先在ArticleResolver中查找author的映射,找不到的属性则一致向下找到属性的java类的get方法/属性本身。

2、接下来我们来看下面的代码

另外,要给Query和Mutation至少创建一个Resolver,这样让root.graphqls中定义的查询和修改方法与对于的Resolver关联起来

package com.hanchao.graphql.graphql.resolver;

import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import com.hanchao.graphql.graphql.entity.Author;
import com.hanchao.graphql.graphql.entity.Book;
import com.hanchao.graphql.graphql.entity.User;
import com.hanchao.graphql.graphql.enums.CountryEnum;
import com.hanchao.graphql.graphql.model.Dog;
import com.hanchao.graphql.graphql.model.Fish;
import com.hanchao.graphql.graphql.model.Animal;
import com.hanchao.graphql.graphql.repo.AuthorRepo;
import com.hanchao.graphql.graphql.repo.BookRepo;
import com.hanchao.graphql.graphql.repo.UserRepo;
import graphql.relay.Connection;
import graphql.relay.SimpleListConnection;
import graphql.schema.DataFetchingEnvironment;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @author hanliwei
 * @create 2019-02-12 18:00
 */
@Component
@AllArgsConstructor
public class Query implements GraphQLQueryResolver {

    private AuthorRepo authorRepo;

    private BookRepo bookRepo;

    private UserRepo userRepo;

    public Author findAuthorById(Long id) {
        return authorRepo.findAuthorById(id);
    }

    public List<Author> findAllAuthors() {
        return authorRepo.findAll();
    }

    public Long countAuthors() {
        return authorRepo.count();
    }

    public List<Book> findAllBooks() {
        return bookRepo.findAll();
    }

    public Long countBooks() {
        return bookRepo.count();
    }

    public Book findBookById(Long id) {
        return bookRepo.findBookById(id);
    }

    public String testEnum(CountryEnum country) {
        return country.toString();
    }

    /**
     * 分页测试
     * @param first
     * @param after
     * @param env
     * @return
     */
    public Connection<Book> books(int first,String after,DataFetchingEnvironment env) {
        return new SimpleListConnection<>(bookRepo.findAll()).get(env);
    }

    /**
     * @descript: 测试一下接口的使用
     * @auther: hanliwei
     * @date: 2019/3/3 18:31
     * @param name
     * @return
     */
    public Animal getAnimal(String name) {
        Dog dog = new Dog();
        dog.setName(name);
        dog.setLegs(4);

        Fish fish = new Fish();
        fish.setName(name);
        fish.setTailColor("BlueAndRead");

        if ("dog".equals(name)) {
            return dog;
        } else if ("fish".equals(name)) {
            return fish;
        }
        return null;
    }

    /**
     * @descript: 返回不同类型的数据
     * @auther: hanliwei
     * @date: 2019/3/3 20:42
     * @return
     */
    public List<Animal> animals() {
        Dog dog = new Dog();
        dog.setName("I am Dog");
        dog.setLegs(4);

        Fish fish = new Fish();
        fish.setName("I am Fish");
        fish.setTailColor("BlueAndRead");

        List<Animal> list = new ArrayList<>();
        list.add(dog);
        list.add(fish);

        return list;
    }
}
Query类中定义的方法名称要和root.graphqls中定义的方法名称一致,这样启动了时候grahql-java-tools这个包能够自定的进行关联扫描起来
package com.hanchao.graphql.graphql.resolver;
 
import com.coxautodev.graphql.tools.GraphQLMutationResolver;
import com.hanchao.graphql.graphql.entity.Author;
import com.hanchao.graphql.graphql.entity.Book;
import com.hanchao.graphql.graphql.model.BookInput;
import com.hanchao.graphql.graphql.repo.AuthorRepo;
import com.hanchao.graphql.graphql.repo.BookRepo;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
 
/**
 * @author hanliwei
 * @create 2019-02-12 18:58
 */
@Component
@AllArgsConstructor
public class Mutation implements GraphQLMutationResolver {
    private AuthorRepo authorRepo;
    private BookRepo bookRepo;
 
    public Author newAuthor(String firstName, String lastName) {
        Author author = new Author();
        author.setFirstName(firstName);
        author.setLastName(lastName);
        return authorRepo.save(author);
    }
 
    public Book newBook(String title, String isbn, int pageCount, Long authorId) {
        Book book = new Book();
        book.setTitle(title);
        book.setIsbn(isbn);
        book.setPageCount(pageCount);
        book.setAuthorId(authorId);
        return bookRepo.save(book);
    }
 
 
    public Book saveBook(BookInput input) {
        Book book = new Book();
        book.setTitle(input.getTitle());
        book.setIsbn(input.getIsbn());
        book.setPageCount(input.getPageCount());
        book.setAuthorId(input.getAuthorId());
        return bookRepo.save(book);
    }
 
    public Boolean deleteBook(Long id) {
        bookRepo.deleteById(id);
        return true;
    }
 
    public Book updateBookPageCount(int pageCount,long id) {
        Book book = bookRepo.findBookById(id);
        book.setPageCount(pageCount);
        return bookRepo.save(book);
    }
 
}

上面就是整个代码的核心原理,接下来我们来看看整个代码

 

 代码的地址位于码云

https://gitee.com/kebibuluan/springboot-grahql

pom.xml如下

<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.an</groupId>
    <artifactId>apollo-demo-datasource</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <project.encoding>UTF-8</project.encoding>
        <apollo.version>1.4.0</apollo.version>
        <platform.bom.version>Cairo-SR2</platform.bom.version>
        <spring.cloud.version>Finchley.RELEASE</spring.cloud.version>
        <druid-boot.version>1.1.20</druid-boot.version>
    </properties>

    <dependencyManagement>
        <dependencies>

            <!-- platform bom -->
            <dependency>
                <groupId>io.spring.platform</groupId>
                <artifactId>platform-bom</artifactId>
                <version>${platform.bom.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- spring cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- apollo -->
            <dependency>
                <groupId>com.ctrip.framework.apollo</groupId>
                <artifactId>apollo-client</artifactId>
                <version>${apollo.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid-boot.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ctrip.framework.apollo</groupId>
            <artifactId>apollo-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-spring-boot-starter</artifactId>
            <version>5.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-java-tools</artifactId>
            <version>5.2.4</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphiql-spring-boot-starter</artifactId>
            <version>5.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
        </dependency>
        <!-- graphQL end -->
        <!-- MYSQL&JPA begin -->
        <!-- MYSQL&JPA end -->
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <!-- 使编译的JDK版本一致为8 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

底层数据量的操作使用了springboot-jpa的功能

 

 

package com.hanchao.graphql.graphql;

import com.coxautodev.graphql.tools.SchemaParserDictionary;
import com.hanchao.graphql.graphql.model.*;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class GraphqlApplication {

    public static void main(String[] args) {
        SpringApplication.run(GraphqlApplication.class, args);
    }

    /*@Bean
    SchemaParserDictionary schemaParserDictionary() {
        return new SchemaParserDictionary()
                .add(CreatedUser.class)
                .add(ErrorContainer.class)
                .add(LoginPayload.class)
                .add(Dog.class)
                .add(Fish.class);
    }*/

}
package com.hanchao.graphql.graphql.config.mysql;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import javax.sql.DataSource;

/**
 * @author hanliwei
 * @create 2019-01-15 15:07
 */
@Configuration
public class DataSourceConfig {
    @Autowired
    private Environment env;

    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setDriverClassName(env.getProperty("jdbc.driver"));
        config.setJdbcUrl(env.getProperty("jdbc.url"));
        config.setUsername(env.getProperty("jdbc.username"));
        config.setPassword(env.getProperty("jdbc.password"));
        /**
         * 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)
         */
        config.setMaximumPoolSize(20);
        config.setMinimumIdle(5);
        /**
         * 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
         */
        config.setConnectionTimeout(5 * 1000L);
        /**
         * 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟
         */
        config.setIdleTimeout(3 * 60 * 1000L);
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        config.setConnectionTestQuery("SELECT 1");
        config.setPoolName("beehive_statistic");
        return new HikariDataSource(config);
    }
}
package com.hanchao.graphql.graphql.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Just for test
 *
 * @author hanliwei
 * @create 2019-02-24 9:27
 */
@RestController
public class HanchaoController {

    @GetMapping("/test")
    public String testSpringBoot() {
        return "Hello, springboot";
    }
}
package com.hanchao.graphql.graphql.entity;

import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.persistence.Column;
import javax.persistence.Entity;


@Entity
@Data
@EqualsAndHashCode(callSuper = false)
public class Author extends BaseEntity {

    @Column(columnDefinition = "varchar(50)")
    private String firstName;

    @Column(columnDefinition = "varchar(50)")
    private String lastName;
}
package com.hanchao.graphql.graphql.entity;

import lombok.Data;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

/**
 * @author hanliwei
 * @create 2019-02-12 17:18
 */
@Data
@MappedSuperclass
public class BaseEntity implements Serializable {


    /** ID */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(columnDefinition = "bigint", nullable = false)
    protected Long id;

    /** 创建时间戳 (单位:秒) */
    @Column(nullable = false, updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    protected Date createdTime;

    /** 更新时间戳 (单位:秒) */
    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    protected Date updatedTime;


    public BaseEntity() {
        createdTime = new Date();
        updatedTime = createdTime;
    }

    @PreUpdate
    private void doPreUpdate() {
        updatedTime = new Date();
    }

}
package com.hanchao.graphql.graphql.entity;

import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.persistence.Column;
import javax.persistence.Entity;


@Entity
@Data
@EqualsAndHashCode(callSuper = false)
public class Book extends BaseEntity {
    @Column(columnDefinition = "varchar(50)")
    private String title;

    private String isbn;

    private int pageCount;

    private long authorId;

    private Double price;
}
package com.hanchao.graphql.graphql.entity;

import lombok.Data;

import javax.persistence.*;

/**
 * @author hanliwei
 * @create 2019-03-02 11:03
 */
@Entity
@Data
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(columnDefinition = "bigint", nullable = false)
    private Long id;
    private String name;
    private Integer age;
    private String email;
    private String pwd;
}
package com.hanchao.graphql.graphql.enums;

/**
 * 单位
 *
 * @author hanliwei
 * @create 2019-02-24 15:02
 */
public enum CountryEnum {
    USA,CHINA;
}

 

 

package com.hanchao.graphql.graphql.model;


/**
 * 为演示GraphQL interface创建的接口
 *
 * @author hanliwei
 * @create 2019-02-20 17:26
 */
public interface Animal {
    String getName();
}
package com.hanchao.graphql.graphql.model;

import lombok.Data;

/**
 * AuthData.java
 *
 * @author hanliwei
 * @create 2019-03-02 11:16
 */
@Data
public class AuthData {
    private String pwd;
    private String email;
}
package com.hanchao.graphql.graphql.model;

        import lombok.Data;


@Data
public class BookInput {
    private String title;

    private String isbn;

    private int pageCount;

    private long authorId;
}
package com.hanchao.graphql.graphql.model;

import com.hanchao.graphql.graphql.entity.User;
import lombok.AllArgsConstructor;
import lombok.Data;

/**
 * CreatedUser.java
 *
 * @author hanliwei
 * @create 2019-03-02 11:14
 */
@Data
@AllArgsConstructor
public class CreatedUser implements CreateUserResult {
    private User user;
}
package com.hanchao.graphql.graphql.model;

/**
 * union CreateUserResult
 *
 * @author hanliwei
 * @create 2019-03-02 11:13
 */
public interface CreateUserResult {
}
package com.hanchao.graphql.graphql.model;

import lombok.Data;

/**
 * 为演示GraphQL interface创建的实现实体
 *
 * @author hanliwei
 * @create 2019-02-20 17:27
 */
@Data
public class Dog implements Animal {

    private String name;
    private int legs;
}
package com.hanchao.graphql.graphql.model;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.List;

/**
 * ErrorContainer.java
 *
 * @author hanliwei
 * @create 2019-03-02 11:15
 */
@Data
@AllArgsConstructor
public class ErrorContainer implements CreateUserResult,LoginResult {
    private List<String> messages;
}
package com.hanchao.graphql.graphql.model;

import lombok.Data;

/**
 * 为演示GraphQL interface创建的实现实体
 *
 * @author hanliwei
 * @create 2019-02-20 17:29
 */
@Data
public class Fish implements Animal {
    private String tailColor;
    private String name;

}
package com.hanchao.graphql.graphql.model;

import com.hanchao.graphql.graphql.entity.User;
import lombok.AllArgsConstructor;
import lombok.Data;

/**
 * @author hanliwei
 * @create 2019-03-02 16:00
 */
@Data
@AllArgsConstructor
public class LoginPayload implements LoginResult{
    private Long token;
    private User user;
}
package com.hanchao.graphql.graphql.model;

/**
 * @author hanliwei
 * @create 2019-03-02 16:00
 */
public interface LoginResult {
}
package com.hanchao.graphql.graphql.repo;


import com.hanchao.graphql.graphql.entity.Author;
import org.springframework.data.jpa.repository.JpaRepository;


/**
 * @author hanliwei
 * @create 2019-02-12 17:29
 */
public interface AuthorRepo extends JpaRepository<Author,Long> {

    Author findAuthorById(Long id);
}
package com.hanchao.graphql.graphql.repo;

import com.hanchao.graphql.graphql.entity.Book;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

/**
 * @author hanliwei
 * @create 2019-02-12 17:31
 */
public interface BookRepo extends JpaRepository<Book,Long> {
    List<Book> findByAuthorId(Long id);

    Book findBookById(Long id);
}
package com.hanchao.graphql.graphql.repo;

import com.hanchao.graphql.graphql.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

/**
 * @author hanliwei
 * @create 2019-03-02 11:18
 */
public interface UserRepo extends JpaRepository<User,Long> {
    /**
     * @descript: 通过用户名查找用户
     * @auther: hanliwei
     * @date: 2019/3/2 11:29
     * @param name  用户名
     * @return User
     */
    User findUserByName(String name);

    User findUserByEmail(String email);

    User findUserByEmailAndPwd(String email,String pwd);

}
package com.hanchao.graphql.graphql.resolver;

import com.coxautodev.graphql.tools.GraphQLResolver;
import com.hanchao.graphql.graphql.entity.Author;
import com.hanchao.graphql.graphql.entity.Book;
import com.hanchao.graphql.graphql.repo.BookRepo;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.List;

/**
 * @author hanliwei
 * @create 2019-02-12 17:33
 */
@Component
@AllArgsConstructor
public class AuthorResolver implements GraphQLResolver<Author> {

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private BookRepo bookRepo;

    public String getCreatedTime(Author author) {
        return sdf.format(author.getCreatedTime());
    }

    public List<Book> getBooks(Author author) {
        return bookRepo.findByAuthorId(author.getId());
    }
}
package com.hanchao.graphql.graphql.resolver;

import com.coxautodev.graphql.tools.GraphQLResolver;
import com.hanchao.graphql.graphql.entity.Author;
import com.hanchao.graphql.graphql.entity.Book;
import com.hanchao.graphql.graphql.enums.CountryEnum;
import com.hanchao.graphql.graphql.repo.AuthorRepo;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;


/**
 * @author hanliwei
 * @create 2019-02-12 17:36
 */
@Component
@AllArgsConstructor
public class BookResolver implements GraphQLResolver<Book> {

    private AuthorRepo authorRepo;

    public Author getAuthor(Book book) {
        return authorRepo.findAuthorById(book.getAuthorId());
    }

    public String getMoney(Book book,CountryEnum country) {
        if (country == CountryEnum.CHINA) {
            return "¥:" + book.getPrice() * 6;
        } else if (country == CountryEnum.USA) {
            return "$:" + book.getPrice();
        } else {
            return "free";
        }
    }
}
package com.hanchao.graphql.graphql.resolver;
 
import com.coxautodev.graphql.tools.GraphQLMutationResolver;
import com.hanchao.graphql.graphql.entity.Author;
import com.hanchao.graphql.graphql.entity.Book;
import com.hanchao.graphql.graphql.model.BookInput;
import com.hanchao.graphql.graphql.repo.AuthorRepo;
import com.hanchao.graphql.graphql.repo.BookRepo;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
 
/**
 * @author hanliwei
 * @create 2019-02-12 18:58
 */
@Component
@AllArgsConstructor
public class Mutation implements GraphQLMutationResolver {
    private AuthorRepo authorRepo;
    private BookRepo bookRepo;
 
    public Author newAuthor(String firstName, String lastName) {
        Author author = new Author();
        author.setFirstName(firstName);
        author.setLastName(lastName);
        return authorRepo.save(author);
    }
 
    public Book newBook(String title, String isbn, int pageCount, Long authorId) {
        Book book = new Book();
        book.setTitle(title);
        book.setIsbn(isbn);
        book.setPageCount(pageCount);
        book.setAuthorId(authorId);
        return bookRepo.save(book);
    }
 
 
    public Book saveBook(BookInput input) {
        Book book = new Book();
        book.setTitle(input.getTitle());
        book.setIsbn(input.getIsbn());
        book.setPageCount(input.getPageCount());
        book.setAuthorId(input.getAuthorId());
        return bookRepo.save(book);
    }
 
    public Boolean deleteBook(Long id) {
        bookRepo.deleteById(id);
        return true;
    }
 
    public Book updateBookPageCount(int pageCount,long id) {
        Book book = bookRepo.findBookById(id);
        book.setPageCount(pageCount);
        return bookRepo.save(book);
    }
 
}
package com.hanchao.graphql.graphql.utils;

import graphql.schema.DataFetchingEnvironment;
import graphql.servlet.GraphQLContext;

import java.util.Optional;

/**
 * @author hanliwei
 * @create 2019-03-02 16:13
 */
public class Utils {
    public static Optional<String> getHeader(String header, DataFetchingEnvironment env) {
        GraphQLContext graphQLContext = env.getContext();
        return graphQLContext.getHttpServletRequest()
                .flatMap(req -> Optional.ofNullable(req.getHeader(header)));
    }

    public static Optional<String> getAuthToken(DataFetchingEnvironment env) {
        Optional<String> auth = getHeader("Authorization", env);
        return auth.map(str -> str.replace("Bearer ", ""));
    }
}

 

 

root.graphqls

#查询入口
type Query {
    ####### Author相关 #########
    findAuthorById(id:Long!): Author
 
    findAllAuthors: [Author]!
 
    countAuthors: Long!
 
    ####### Book相关 #########
    findAllBooks: [Book]!
    countBooks: Long!
}
 
type Mutation {
    newAuthor(firstName: String!,lastName: String!) : Author!
 
    newBook(title: String!,isbn: String!,pageCount: Int, authorId: Long!) : Book!
    saveBook(input: BookInput!) : Book!
    deleteBook(id: ID!) : Boolean
    updateBookPageCount(pageCount: Int!, id:Long!) : Book!
}

schema.graphqls

type Author {
    #作者Id
    id: Long!
    #创建时间
    createdTime: String
    #名
    firstName: String
    #姓
    lastName: String
    #该作者的所有书籍
    books: [Book]
}
 
input BookInput {
    title: String!
    isbn: String!
    pageCount: Int
    authorId: Long
}
 
type Book {
    id: Long!
    title: String!
    isbn: String!
    pageCount: Int
    author: Author
}

application.properties

server.port=8001

############ mysql-开始 ###########
#启动时会根据实体类生成数据表,或者更新表结构,不清空数据,开发阶段使用;validate:表结构稳定后使用,可用于正式环境;
spring.jpa.hibernate.ddl-auto=update
#控制台打印Sql
spring.jpa.show-sql=true
#让控制器输出的json格式更美观
spring.jackson.serialization.indent-output=true

#datasource
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/grahql?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useServerPrepStmts=true&jdbcCompliantTruncation=false
jdbc.username=root
jdbc.password=123456
############ mysql-结束 ###########

application.yml

我们把项目启动起来,访问下面的地址就可以访问了数据库了

 

 

 

 

posted on 2020-12-08 19:57  luzhouxiaoshuai  阅读(520)  评论(0编辑  收藏  举报

导航