何时是使用GORM运行自动迁移的适当时机

ecbunoof  于 2023-01-06  发布在  Go
关注(0)|答案(1)|浏览(154)

我看过的大多数Go/GORM例子都是在打开数据库连接后立即调用Automigrate,包括GORM文档here。对于API服务来说,这将是一个昂贵的/需要的调用。所以,我认为,对于API服务来说,Automigrate应该从常规流中移除,并单独处理。我的理解对吗?
GORM Documentation

...
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
  panic("failed to connect database")
}

// Migrate the schema
db.AutoMigrate(&Product{})
...
hec6srdp

hec6srdp1#

它不会发生在每个API请求上,甚至不会接近。它会发生在每次启动应用程序时,所以基本上:连接到main中的DB,并在那里运行AutoMigrate。将连接作为依赖项传递到您的处理程序/service packages/任何您需要它们的地方。HTTP处理程序可以在那里访问它。
基本上是这样的:

package main

func main() {
    db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    if err != nil {
        fmt.Printf("Failed to connect to DB: %v", err)
        os.Exit(1)
    }
    // see below how this is handled
    fRepo := foo.New(db) // all repos here
    fRepo.Migrate() // this handles migrations
    // create request handlers
    fHandler := handlers.NewFoo(fRepo) // migrations have already been handled
    mux := http.NewServeMux()
    mux.HandleFunc("/foo/list", fHandler.List) // set up handlers
    // start server etc...
}

将与DB交互的代码放在某个包中,如下所示:

package foo

// The DB connection interface as you use it
type Connection interface {
    Create()
    Find()
    AutoMigrate(any)
}

type Foo struct {
    db Connection
}

func New(db Connection) *Foo {
    return &Foo{
        db: db,
    }
}

func (f *Foo) Migrate() {
    f.db.AutoMigrate(&Stuff{}) // all types this repo deals with go here
}

func (f *Foo) GetAll() ([]Stuff, error) {
    ret := []Stuff{}
    res := f.db.Find(&ret)
    return ret, res.Error
}

然后让你的处理程序以一种合理的方式进行结构化,并为它们提供存储库(aka foo package stuff):

package handlers

type FooRepo interface {
    GetAll() ([]Stuff, error)
}

type FooHandler struct {
    repo FooRepo
}

func NewFoo(repo FooRepo) *FooHandler {
    return &FooHandler{
        repo: repo,
    }
}

func (f *FooHandler) List(res http.ResponseWriter, req *http.Request) {
    all, err := f.repo.GetAll()
    if err != nil {
        res.WriteHeader(http.StatusInternalServerError)
        io.WriteString(w, err.Error())
        return
    }
    // write response as needed
}

每当您部署应用程序的更新版本时,main函数将调用AutoMigrate,应用程序将处理请求,而无需不断地重新连接到DB或一次又一次地尝试处理迁移。
我不知道为什么你会认为你的应用程序必须为每个请求运行一遍设置,特别是考虑到你的主函数(或者你从main调用的某个函数)显式地创建了一个HTTP服务器,并在特定的端口上侦听请求。DB连接和后续的迁移应该在你开始侦听请求之前处理。它不是处理请求的一部分,永远...

相关问题