Handling databases using gorm
728x90
python에 이어서 orm의 맛을 본 저는 go에서도 sqlx을 걷어내고 orm 을 도입하기로 했습니다.
github 에서 압도적인 스타수를 자랑하고 엄청난 기능을 지원해줘서 도입하게 되었습니다.
go 에서 구조체와 마샬링 언마샬링과의 궁합도 찰떡이고 에러 핸들링 및 트랜잭션 또한 매우 쉽게 할수 있습니다.
Connection
.env 파일 정의하기
SERVER_ADDRESS=0.0.0.0
SERVER_PORT=3070
DB_USER_NAME=
DB_USER_PASSWORD=
DB_NAME=postgres
DB_PORT=5432
DB_HOST=
본인의 정보에 맞게 입력해주시면 됩니다
db/init.go
package db
import (
"device-scheduler/logger"
"fmt"
"os"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func GetDbClient() *gorm.DB {
dbUser := os.Getenv("DB_USER_NAME")
dbPasswd := os.Getenv("DB_USER_PASSWORD")
dbHost := os.Getenv("DB_HOST")
dbPort := os.Getenv("DB_PORT")
dbName := os.Getenv("DB_NAME")
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s TimeZone=Asia/Seoul", dbHost, dbUser, dbPasswd, dbName, dbPort)
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("Database not connected error")
}
logger.Info(fmt.Sprintf("Dabase connect success || DB -> %s:%s", dbHost, dbPort))
return db
}
db 를 연결하고 연결에 실패하면 panic을 발생하여 앱을 종료합니다
cmd/routes.go
package main
import (
"device-scheduler/db"
"device-scheduler/domain"
"device-scheduler/internal/handlers"
"device-scheduler/service"
"net/http"
"github.com/bmizerany/pat"
)
// routes defines the application routes
func routes() http.Handler {
mux := pat.New()
dbClient := db.GetDbClient()
deviceRepositoryDb := domain.NewDeviceRepositoryDb(dbClient)
dh := handlers.DeviceHandler{service.NewDeviceService(deviceRepositoryDb)}
mux.Get("/ws", http.HandlerFunc(dh.WsEndpoint))
return mux
}
dbClient를 넘겨받고 저장소를 만들어 서비스에 넘겨줍니다.
이렇게 한이유는 추후에 테스트코드를 작성할때 mock객체를 만들어 테스트 하기 위함입니다.
Define Model
package domain
import (
"device-scheduler/errs"
)
// Device shop_device table
type Device struct {
ShopDeviceId int64 `gorm:"column:shop_device_id"`
ShopId int `gorm:"column:shop_id"`
PanelId string `gorm:"column:panel_id"`
SettopId string `gorm:"column:settop_id"`
ShopDisplayId int `gorm:"column:shop_display_id"`
Status int `gorm:"column:status"`
SortNo int `gorm:"column:sort_no"`
VideoURL string `gorm:"column:whole_display_path"`
ThumbnailURL string `gorm:"column:thumbnail_path"`
}
type DeviceRepository interface {
FindById(deviceId int) (*Device, *errs.AppError)
FindAllActive() ([]Device, *errs.AppError)
}
컬럼명이 다른경우 직접 명시해줄수 있습니다. 인덱스 및 pk 값도 설정할 수 있습니다. 더 자세한 내용은 공식문서를 참고해주세요!
Example Query & Error handling
func (d DeviceRepositoryDb) FindById(deviceId int) (*Device, *errs.AppError) {
var device Device
if err := d.Client.Table("device").Where("id = ? AND path IS NOT NULL", deviceId).First(&device).Error; err != nil {
logger.Error("Error while find by device id " + err.Error())
return nil, errs.NewUnexpectedError("Unexpected database error")
}
return &device, nil
}
func (d DeviceRepositoryDb) FindAllActive() ([]Device, *errs.AppError) {
devices := make([]Device, 0)
if err := d.Client.Table("device").Where("path IS NOT NULL AND NOT status = 0").Find(&devices).Error; err != nil {
logger.Error("Error while find all active device " + err.Error())
return nil, errs.NewUnexpectedError("Unexpected database error")
}
for _, r := range devices {
fmt.Println(r)
}
return devices, nil
}
Table 명을 직접 명시할 수 있고 슬라이스를 만들어 여러개의 Row를 할당 할수 있습니다. Find 절이 끝나는 곳에서 .Error를 하게 되었을땐 아무것도 찾지 못하면 Error 를 내뱉게 됩니다.
728x90
'Go' 카테고리의 다른 글
Fibonacci 로 알아보는 동시성 과 클로저 (0) | 2021.10.26 |
---|---|
Publisher Subscriber pattern (발행 구독 패턴) (0) | 2021.10.25 |
Go interface: 대소문자 의 의미 (0) | 2021.10.20 |
Docker 로 Go 프로젝트 빌드 & 실행하기 (0) | 2021.10.05 |
Go - 삽입정렬 구현하기 (0) | 2021.10.03 |
댓글
이 글 공유하기
다른 글
-
Fibonacci 로 알아보는 동시성 과 클로저
Fibonacci 로 알아보는 동시성 과 클로저
2021.10.26 -
Publisher Subscriber pattern (발행 구독 패턴)
Publisher Subscriber pattern (발행 구독 패턴)
2021.10.25 -
Go interface: 대소문자 의 의미
Go interface: 대소문자 의 의미
2021.10.20 -
Docker 로 Go 프로젝트 빌드 & 실행하기
Docker 로 Go 프로젝트 빌드 & 실행하기
2021.10.05