graphql api graphiql graphql multiple queries in one request

GraphQL EP 5:從資料庫讀取資料並輸出

透過GraphQL查詢資料庫的資料

在【GraphQL EP 1:GraphQL API一種更簡單、靈活的資料輸出方式】文章中,輸出的資料是直接從程式或Query帶參數產生的,但更多的應用其實是從資料庫將資料讀取出來,所以本篇就是要分享如何如何使用GraphQL透過Spring Boot JPA向資料庫讀取資料。

實作本篇前,請先:

  1. 安裝資料庫:在CentOS 7安裝MariaDB
  2. 準備資料:Spring Boot EP 9:準備資料庫(MariaDB)及資料(市場指數及個股每日股價)
  3. 學會Spring Boot JPA與Hibernate:Spring Boot EP 10:透過Spring Data JPA與Hibernate讀取(select)資料庫

結構

本篇專案會建立幾個Package,其用途如下:

main/java/com.example.graphqldemo:

  • entities:定義資料庫欄位的資料模型,與資料庫表格為對應關係,或是對應資料輸出的欄位。
  • ids:定義entities內資料模型的主鍵(Key)。
  • queries:實作GraphQL的Resolver,GraphQL Query所要輸出資料的函數都在此。
  • repositories:實作Spring Data JPA之所在。
  • services:
    • interface:讀取資料庫的程式撰寫於此,不論使用Hibernate或其他方式。
    • implements:實作interface service,對應repositories。

main/

  • resources:創建副檔名為”.graphqls”的檔案,裏面描述了如何對GraphQL操作Query與輸入/輸出的資料。

實作

第1步:先看一下資料表”MARKETS”這張Table。

第2步:entities建立”MarketEntity.java”。

package com.example.graphqldemo.entities;

import lombok.*;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Getter
@Setter
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "MARKETS")
public class MarketEntity {

    @Id
    @Column(name = "MARKET_CODE", nullable = false)
    private String MarketCode;

    @Column(name = "MARKET_NAME", nullable = false)
    private String MarketName;
}

第3步:repositories建立”MarketRepository.java”。

package com.example.graphqldemo.repositories;

import com.example.graphqldemo.entities.MarketEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MarketRepository extends JpaRepository<MarketEntity, String> {
}

第4步:services建立”MarketService.java”,並將操作資料庫的SQL語法撰寫於此。

package com.example.graphqldemo.services;

import com.example.graphqldemo.entities.MarketEntity;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface MarketService {
    @Query(value = "SELECT MARKET_CODE, MARKET_NAME FROM STOCK_MARKET.MARKETS;", nativeQuery = true)
    List<MarketEntity> getAll();

    @Query(value = "SELECT MARKET_CODE, MARKET_NAME FROM STOCK_MARKET.MARKETS WHERE MARKET_CODE=:MARKET_CODE", nativeQuery = true)
    MarketEntity getByMarketCode(@Param("MARKET_CODE") String MarketCode);
}

第5步:services建立”MarketServiceImpl.java”,實作”MarketService”。

package com.example.graphqldemo.services;

import com.example.graphqldemo.entities.MarketEntity;
import com.example.graphqldemo.repositories.MarketRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
@AllArgsConstructor
public class MarketServiceImpl implements MarketService{
    private final MarketRepository marketRepository;

    @Override
    public List<MarketEntity> getAll() {
        return marketRepository.findAll();
    }

    @Override
    public MarketEntity getByMarketCode(String MarketCode) {
        Optional<MarketEntity> marketEntity = marketRepository.findById(MarketCode);
        return marketEntity.orElse(null);
    }
}

第6步:於queries建立”MarketQuery.java”,實作GraphQLQueryResolver。

package com.example.graphqldemo.queries;

import com.example.graphqldemo.entities.MarketEntity;
import com.example.graphqldemo.services.MarketService;
import graphql.kickstart.tools.GraphQLQueryResolver;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@RequiredArgsConstructor
public class MarketQuery implements GraphQLQueryResolver {
    private final MarketService marketService;

    public List<MarketEntity> Markets(){
        return  marketService.getAll();
    }

    public MarketEntity Market(String MarketCode){
        return marketService.getByMarketCode(MarketCode);
    }
}

7步:resources建立”market.graphqls”,對應”MarketQuery.java”所實作的GraphQLQueryResolver查詢函數。

# 定義Market的資料模型,對應資料庫的欄位
type Market {
    MarketCode: String!
    MarketName: String
}

# 對應GraphQLQueryResolver的函數設計查詢語法
extend type Query {
    Markets: [Market]!
    Market(MarketCode: String!): Market
}

第8步:透過GraphiQL的畫面可以看到剛剛定義的兩個API,如下圖紅匡處所示。

第8步:在GraphiQL下GraphQL Query,可以選擇需要的欄位,如下圖,將所有欄位都顯示出來。

也可以指定MarketName這個欄位:

~ END ~


,

Related posts

Latest posts