GraphQL＋SpringDataJDBCを試してみた

# GraphQLを試してみました
（注意）本記事は2020年09月時点の情報です。

## 0. 参考
+ 初めてのGraphQL ―Webサービスを作って学ぶ新世代API

https://www.amazon.co.jp/%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AEGraphQL-%E2%80%95Web%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E5%AD%A6%E3%81%B6%E6%96%B0%E4%B8%96%E4%BB%A3API-Eve-Porcello/dp/487311893X

- Spring Boot + GraphQLでAPIを作成してみよう！

https://techblog.yahoo.co.jp/advent-calendar-2018/create-springbook-graphql-api/

## 1. GraphQLとは？
+ 数学のグラフ理論に基づく（グラフ理論：一筆書き問題などの学問）
+ Web APIのためのクエリ言語
+ 様々な言語で実装可能
+ RESTの課題を解決しようとした
+ Facebookが2015年に公開

### インスタグラムでのイメージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305683/2efe5638-8b8b-3517-625b-9e3f5590a0ce.png)


### その前にREST APIとの比較
+ スターウォーズAPI（REST版）

```
curl https://swapi.dev/api/people/1/
```
レスポンス

```
{
    "name":  "Luke Skywalker",
    "height":  "172",
    "mass":  "77",
    "hair_color":  "blond",
～省略～
    "gender":  "male",
    "homeworld":  "http://swapi.dev/api/planets/1/",
    "films":  [
                  "http://swapi.dev/api/films/1/",
                  "http://swapi.dev/api/films/2/",
                  "http://swapi.dev/api/films/3/",
                  "http://swapi.dev/api/films/6/"
              ],
～省略～
    "url":  "http://swapi.dev/api/people/1/"
}
```
***
+ スターウォーズAPI（GraphQL版）

```
curl https://swapi.apis.guru/ -ContentType application/json -Body '{"query":"{person(personID:1){name,gender,filmConnection{films{title}}}}"}' 
```

クエリの部分だけ整形すると
__これがGraphQLのクエリ！__

```
{query:
  {person(personID:1)
    {name,
      gender,
      filmConnection
        {films
          {title}
        }
     }
   }
}
```

レスポンス

```
{
  "data":  {
     "person":  {
      "name":  "Luke Skywalker",
      “gender”: “male”,
      "filmConnection":  {
           "films":  [
             {
             "title":  "A New Hope"
             },
             {
             "title":  "The Empire Strikes Back"
             },
             {
             "title":  "Return of the Jedi"
             },
             {
             "title":  "Revenge of the Sith"
             }
             ]
           }
      }
   }
}
```
***
#### RESTとGraphQLを比較すると

+ RESTは多様なエンドポイントURI
+ RESTは過剰取得
+ GraphQLは階層構造も取得
+ GraphQLは日本語情報が少ない
+ GraphQLはライブラリ・ツール類がReactなどのjs系が中心

## 2. GraphQLの言語仕様
### 書籍にお任せして、省略

## 3. GraphQL＋SpringDataJDBCを使ってPostgreSQLからデータ取得
### 依存関係
+ SpringInitializrでBoot、Gradle、SpringDataJDBC
+ PostgreSQLのjdbc4.jar
+ GraphQL系↓

```
// 必須
implementation "com.graphql-java-kickstart:graphql-spring-boot-starter:7.1.0“
// 任意（ブラウザ上でクエリを書ける便利ツール）
implementation "com.graphql-java-kickstart:graphiql-spring-boot-starter:7.1.0"
```

### Entityクラス
+ Authテーブル

```
public class Auth {
	
	@Id
	private long auth_id;
	private long person_id;
	private String login_id;
	private String pass_modify_date;
	
	～getter/setter～
}
```

### Repositoryクラス
+ GraphQL関係ない。SpringDataJDBCの書き方。__実装クラス不要__

```
public interface AuthRepository 
　　extends CrudRepository<Auth, Long> {

}
```

### Resolverクラス
```
@Component
public class AuthResolver implements GraphQLQueryResolver {
	
	private final AuthRepository repository;
	
	@Autowired
	public AuthResolver(AuthRepository repository) {
		this.repository = repository;
	}
	
	public Auth getUserById(long auth_id) {
		
		// Spring Data JDBCでDBアクセス
		Optional<Auth> optAuth = repository.findById(auth_id);
		Auth result = optAuth.orElse(new Auth());
		return result;
	}

}
```

### スキーマ定義

```
type Auth {
  auth_id: ID!
  person_id: Int
  login_id: String
  pass_modify_date: String
}

type Query {
  getUserById(auth_id: ID!): Auth
}
```

### 実行例
+ 実行クエリ

```
query{
  getUserById(auth_id:100) {
    auth_id
    person_id
    login_id
    pass_modify_date
  }
}
```

+ レスポンス

```
{
  "data": {
    "getUserById": {
      "auth_id": "100",
      "person_id": 1111111111,
      "login_id": "kyotokyoto@test.test",
      "pass_modify_date": "2021-05-24 18:00:00.000"
    }
  }
}
```

## 4. おわりに
+ （このレベルのデモであれば）割と簡単に実装できた
+ 実際にエンタープライズで導入する際は、色々カベはありそう
+ GraphQLのクエリを書くのは楽しい
+ RESTfull APIを設計する時の悩みは確かに解消される気がする
+ Javaだとまだライブラリや情報が少ないかも
+ 個人的にはもう少し流行って欲しいな～