postgresql 使用GORM + Postgres + Go Gin + Graphql创建前自动生成UUID

ujv3wf0j  于 2022-12-12  发布在  PostgreSQL
关注(0)|答案(2)|浏览(248)

Is there any way to auto generate UUID with GORM while saving the object in DB in go?
I am having experience with ROR migrations, where ID would be auto generated and PK by default.
Here is my code
Todo.go

package model

type Todo struct {
    ID     string `json:"id"`
    Text   string `json:"text"`
    Done   bool   `json:"done"`
}

schema.resolvers.go

func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) {
    db, _ := database.connect()
    defer db.Close()

    todo := &model.Todo{
        Text:   input.Text,
        ID:     fmt.Sprintf("%d", rand.Int()),  // I don't want to provide ID like this
    }
    db.Create(&todo)
    ...
}

models_gen.go

# GraphQL schema example
#
# https://gqlgen.com/getting-started/

type Todo {
  id: ID!
  text: String!
  done: Boolean!
}

input NewTodo {
  text: String!
  userId: String!
}

type Mutation {
  createTodo(input: NewTodo!): Todo!
}

Any help would be really appreciated.

vtwuwzda

vtwuwzda1#

Assuming you're using gorm v2, you can use hooks to achieve this. The documentation about hooks is here
In particular, you can have a look at the BeforeCreate hook. Applied on a model , it provides a container for a function to be run before the creation in the database as its name state.
The GORM documentation also provides an example to generate a UUID when we create a user entity in a database with Gorm, which seems to be what you're looking for:

func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
  u.UUID = uuid.New()

  if !u.IsValid() {
    err = errors.New("can't save invalid data")
  }
  return
}
anauzrmj

anauzrmj2#

GORM Hooks is the most obvious solution to generate UUID when creating an object.

func (t *Todo) BeforeCreate(tx *gorm.DB) (err error) {
    t.ID = uuid.New().String()
    return
}

But if you want to generate UUID for every object, you could define a base struct and embed it into object structs.

type Base struct {
    ID string `json:"id"`
}

func (b *Base) BeforeCreate(tx *gorm.DB) (err error) {
    b.ID = uuid.New().String()
    return
}

type Todo struct {
    Base
    Text string `json:"text"`
    Done bool   `json:"done"`
}

type User struct {
    Base
    Name string `json:"name"`
}

Or just use the GORM plugin next to generate UUID for objects.

import "github.com/invzhi/next"

plugin := NewPlugin()
// register uuid generate function
plugin.Register("uuid", func(_, zero bool) (interface{}, error) {
    if !zero {
        return nil, SkipField
    }
    return uuid.New().String()
})

_ = db.Use(plugin)

type Todo struct {
    ID   string `gorm:"type:varchar(20);column:id;next:uuid"` // next:uuid meaning generate uuid when create
    Text string `gorm:"type:varchar(100);column:text`
    Done bool   `gorm:"type:boolean;column:done`
}

type User struct {
    ID   string `gorm:"type:varchar(20);column:id;next:uuid"` // next:uuid meaning generate uuid when create
    Name string `gorm:"type:varchar(100);column:name"`
}

相关问题