iT邦幫忙

0

Golang - GraphQL - Database

  • 分享至 

  • xImage
  •  

Introduction

上一篇我們用 GraphQL 已經有個基本的認識
接著來模擬真實的情境搭配 Database 來使用
這篇主要都是在初始化環境

Sample Code

Setup MySQL database by Docker

Create MySQL database

$ docker exec -it mysql bash
$ mysql -u root -p
$ CREATE DATABASE hackernews;

Models and migrations

接著我們需要利用 https://github.com/golang-migrate/migrate 這個 Package 來處理 Migrations

依照下列結構創建資料夾

go-graphql-hackernews
--internal
----pkg
------db
--------migrations
----------mysql

最後所有步驟完成後的資料夾分佈
https://ithelp.ithome.com.tw/upload/images/20230505/20118878pWR6aMwoep.png

依照指令初始化 migrate package

中間遇到缺少的 dependency 就看 console 指示用 go get 抓下來

$ go get -u github.com/go-sql-driver/mysql
$ go build -tags 'mysql' -ldflags="-X main.Version=1.0.0" -o $GOPATH/bin/migrate
$ github.com/golang-migrate/migrate/v4/cmd/migrate/
$ cd internal/pkg/db/migrations/
$ migrate create -ext sql -dir mysql -seq create_users_table
$ migrate create -ext sql -dir mysql -seq create_links_table

接著會看到幾個創建好的 .sql

000001_create_users_table.up.sql 內新增

CREATE TABLE IF NOT EXISTS Users(
    ID INT NOT NULL UNIQUE AUTO_INCREMENT,
    Username VARCHAR (127) NOT NULL UNIQUE,
    Password VARCHAR (127) NOT NULL,
    PRIMARY KEY (ID)
)

000002_create_links_table.up.sql 內新增

CREATE TABLE IF NOT EXISTS Links(
    ID INT NOT NULL UNIQUE AUTO_INCREMENT,
    Title VARCHAR (255) ,
    Address VARCHAR (255) ,
    UserID INT ,
    FOREIGN KEY (UserID) REFERENCES Users(ID) ,
    PRIMARY KEY (ID)
)

cd 回到根目錄執行

$ migrate -database mysql://root:dbpass@/hackernews -path internal/pkg/db/migrations/mysql up

internal/pkg/db/mysql 新增 mysql.go

package database

import (
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"github.com/golang-migrate/migrate"
	"github.com/golang-migrate/migrate/database/mysql"
	_ "github.com/golang-migrate/migrate/source/file"
	"log"
)

var Db *sql.DB

func InitDB() {
	// Use root:dbpass@tcp(172.17.0.2)/hackernews, if you're using Windows.
	db, err := sql.Open("mysql", "root:dbpass@tcp(localhost)/hackernews")
	if err != nil {
		log.Panic(err)
	}

	if err = db.Ping(); err != nil {
 		log.Panic(err)
	}
	Db = db
}

func CloseDB() error {
	return Db.Close()
}

func Migrate() {
	if err := Db.Ping(); err != nil {
		log.Fatal(err)
	}
	driver, _ := mysql.WithInstance(Db, &mysql.Config{})
	m, _ := migrate.NewWithDatabaseInstance(
		"file://internal/pkg/db/migrations/mysql",
		"mysql",
		driver,
	)
	if err := m.Up(); err != nil && err != migrate.ErrNoChange {
		log.Fatal(err)
	}

}

改寫 server.go

這段我有改寫一些,教學的sample直接拿來用會報錯,改了幾個地方

  1. mysql.go 程式碼的 package 改名為 mig,不然會抓不到 import
  2. go get -u github.com/go-chi/chi/v5 抓取需要初始化 HTTP router 的 package
  3. hackernews.XXX() 前綴打錯了,改成 graph.XXX()
func main() {
	port := os.Getenv("PORT")
	if port == "" {
		port = defaultPort
	}

	router := chi.NewRouter()

	mig.InitDB()
	defer mig.CloseDB()
	mig.Migrate()
	server := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}}))
	router.Handle("/", playground.Handler("GraphQL playground", "/query"))
	router.Handle("/query", server)

	log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
	log.Fatal(http.ListenAndServe(":"+port, router))
}

Reference


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言