32 Setup ORM (gorm) di graphql-go
32 Setup ORM (gorm) di graphql-go: Panduan Terpadu untuk Engineer Backend
Bagi engineer backend di ekosistem Go (Golang), membangun API yang robust seringkali memerlukan integrasi antara database, ORM, dan schema GraphQL. Dua tools populer di dunia Go, yaitu gorm sebagai ORM dan graphql-go sebagai server GraphQL, menjadi pilihan utama banyak tim. Artikel ini akan membahas setup gorm dalam proyek graphql-go secara mendalam, dilengkapi contoh kode, simulasi, diagram alur, serta tips-tips engineer yang sudah matang.
🛠 Persiapan: Instalasi Dependency
Sebelum menulis kode, pastikan package berikut sudah terpasang:
1go get github.com/jinzhu/gorm
2go get github.com/go-sql-driver/mysql
3go get github.com/graph-gophers/graphql-go
4go get github.com/graph-gophers/graphql-go/relayKita akan menggunakan MySQL pada contoh ini. Silakan ganti dengan driver lain sesuai kebutuhan (postgres, sqlite, dll).
👩💻 Skema & Requirement di Proyek
Kita bakal mensimulasikan skenario sederhana:
Use Case: Mengelola daftar user.
- Setiap user punya: id, name, email.
Skema Database
1CREATE TABLE users (
2 id INT AUTO_INCREMENT PRIMARY KEY,
3 name VARCHAR(100),
4 email VARCHAR(100) UNIQUE
5);Skema GraphQL
1type User {
2 id: ID!
3 name: String!
4 email: String!
5}
6
7type Query {
8 users: [User!]!
9 user(id: ID!): User
10}
11type Mutation {
12 createUser(name: String!, email: String!): User
13}👨🔬 Integrasi gorm ke graphql-go, Step-by-step
Let’s break it down!
1. Model GORM untuk User
1// models/user.go
2package models
3
4import "github.com/jinzhu/gorm"
5
6type User struct {
7 gorm.Model
8 Name string `gorm:"type:varchar(100)"`
9 Email string `gorm:"type:varchar(100);unique"`
10}2. Setup Database & Auto Migrate
1// db/db.go
2package db
3
4import (
5 "github.com/jinzhu/gorm"
6 _ "github.com/go-sql-driver/mysql"
7 "log"
8 "user-gql/models"
9)
10
11func InitDB() *gorm.DB {
12 db, err := gorm.Open("mysql", "root:password@/userdb?charset=utf8&parseTime=True")
13 if err != nil {
14 log.Fatal(err)
15 }
16 db.AutoMigrate(&models.User{})
17 return db
18}3. Resolver GraphQL
Resolver adalah ‘jembatan’ antara query/mutation GraphQL dan kode Go (termasuk ORM-nya).
1// resolver/resolver.go
2package resolver
3
4import (
5 "context"
6 "user-gql/models"
7 "github.com/jinzhu/gorm"
8)
9
10type Resolver struct {
11 DB *gorm.DB
12}
13
14// Untuk users query
15func (r *Resolver) Users(ctx context.Context) ([]*UserResolver, error) {
16 var users []models.User
17 if err := r.DB.Find(&users).Error; err != nil {
18 return nil, err
19 }
20 resolvers := make([]*UserResolver, len(users))
21 for i, user := range users {
22 resolvers[i] = &UserResolver{user}
23 }
24 return resolvers, nil
25}
26
27// Query tunggal berdasarkan ID
28func (r *Resolver) User(ctx context.Context, args struct{ ID int32 }) (*UserResolver, error) {
29 var user models.User
30 if err := r.DB.First(&user, args.ID).Error; err != nil {
31 return nil, err
32 }
33 return &UserResolver{user}, nil
34}
35
36// Mutation
37func (r *Resolver) CreateUser(ctx context.Context, args struct{ Name string; Email string }) (*UserResolver, error) {
38 user := models.User{Name: args.Name, Email: args.Email}
39 if err := r.DB.Create(&user).Error; err != nil {
40 return nil, err
41 }
42 return &UserResolver{user}, nil
43}
44
45// Resolver untuk User type
46type UserResolver struct {
47 models.User
48}
49
50func (u *UserResolver) ID() graphql.ID { return graphql.ID(fmt.Sprint(u.User.ID)) }
51func (u *UserResolver) Name() string { return u.User.Name }
52func (u *UserResolver) Email() string { return u.User.Email }4. Schema GraphQL
Buat file schema.graphql dengan isi:
1type User {
2 id: ID!
3 name: String!
4 email: String!
5}
6
7type Query {
8 users: [User!]!
9 user(id: ID!): User
10}
11type Mutation {
12 createUser(name: String!, email: String!): User
13}5. Integrasi Handler HTTP
1// main.go
2package main
3
4import (
5 "io/ioutil"
6 "net/http"
7 "user-gql/db"
8 "user-gql/resolver"
9
10 "github.com/graph-gophers/graphql-go"
11 "github.com/graph-gophers/graphql-go/relay"
12)
13
14func main() {
15 // Setup DB
16 database := db.InitDB()
17 defer database.Close()
18
19 // Load schema
20 schemaBytes, err := ioutil.ReadFile("schema.graphql")
21 if err != nil {
22 panic(err)
23 }
24
25 // Buat schema GraphQL
26 schema := graphql.MustParseSchema(
27 string(schemaBytes),
28 &resolver.Resolver{DB: database},
29 )
30
31 http.Handle("/query", &relay.Handler{Schema: schema})
32
33 // Live!
34 http.ListenAndServe(":8080", nil)
35}🏃 Simulasi Query ke Server
1. Query Seluruh User
1query {
2 users {
3 id
4 name
5 email
6 }
7}Respons:
1{
2 "data": {
3 "users": [
4 {"id": "1", "name": "Ridwan", "email": "ridwan@contoh.com"},
5 {"id": "2", "name": "Rahma", "email": "rahma@company.com"}
6 ]
7 }
8}2. Mutation: Tambah User
1mutation {
2 createUser(name: "Bimo", email: "bimo@team.com") {
3 id
4 name
5 }
6}📊 Tabel: Perbandingan GORM vs Raw SQL
| Fitur | GORM | Raw SQL |
|---|---|---|
| Query Builder | YES (ORM style) | NO |
| Auto Migration | YES | NO |
| Relations | YES (Preload, Joins) | Manual (Join) |
| Struct Mapping | YES (Struct to Table) | Handcrafted |
| Error Handling | Tengah (ada error type) | Manual/Error bawaan |
| Readability | Lebih clean & idiomatic | Kadang verbose |
🔖 Diagram Alur Setup
flowchart TD
A[Inisiasi: Load Schema GraphQL] --> B[Init GORM DB]
B --> C[Bind Resolver ke GORM DB]
C --> D[GraphQL HTTP Handler aktif]
D --> E[Receive HTTP Request /query]
E --> F{Jenis Query}
F -- Query user/users --> G[GORM query ke DB]
F -- Mutation --> H[GORM transaksi ke DB]
G & H --> I[Json Response via GraphQL]
⚡️ Engineering Tips
- Connection Pool: Gunakan
db.DB().SetMaxOpenConns(...)untuk optimasi performance. - Env Config: Simpan credential database di environment variable, bukan hardcoded.
- Validation: Validasi input di mutation sebelum commit ke DB (jangan terlalu percaya kepada client!).
- Migration: Jalankan migration secara terpisah di production, jangan dari main app.
- Testing: Gunakan test DB untuk integration test, mocking GORM dengan library seperti go-sqlmock .
💬 Penutup
Dengan setup seperti di atas, kamu dapat menghubungkan orm GORM dan graphql-go dengan clean, rapi, dan maintainable. Kuncinya: selalu treat resolver sebagai lapisan bersih yang menghubungkan dunia GraphQL dengan ORM/db-mu.
Jangan ragu untuk mengadaptasi pattern ini ke kebutuhan proyekmu, baik untuk e-commerce, SaaS, atau skala enterprise. Jika ada pertanyaan atau butuh penjelasan lebih lanjut, drop di komentar 😉
References:
Selamat ngoding, backend warriors! 🚀