How do you do UUID in Golangs Gorm?

huangapple go评论89阅读模式
英文:

How do you do UUID in Golangs Gorm?

问题

我有以下模型...

type User struct {
    ID        string  `sql:"type:uuid;primary_key;default:uuid_generate_v4()"`
    FirstName string `form:"first_name" json:"first_name,omitempty"`
    LastName  string `form:"last_name" json:"last_name,omitempty"`
    Password  string `form:"password" json:"password" bindind:"required"`
    Email     string `gorm:"type:varchar(110);unique_index" form:"email" json:"email,omitempty" binding:"required"`
    Location  string `form:"location" json:"location,omitempty"`
    Avatar    string `form:"avatar" json:"avatar,omitempty"`
    BgImg     string `form:"bg_img" json:"bg_img,omitempty"`
    CreatedAt time.Time
    UpdatedAt time.Time
    DeletedAt time.Time
}

我尝试了几种不同的方法,但是这种方式会抛出"(pq: relation "users" does not exist)"的错误。我没有相关的模型,只有这一个模型。

我尝试使用...

func (user *User) BeforeCreate(scope *gorm.Scope) error {
    scope.SetColumn("ID", uuid.NewV4())
    return nil
}

还使用了一个uuid库,但是也没有成功。

英文:

I have the following model...

type User struct {
    ID        string  `sql:"type:uuid;primary_key;default:uuid_generate_v4()"`
	FirstName string `form:"first_name" json:"first_name,omitempty"`
	LastName  string `form:"last_name" json:"last_name,omitempty"`
	Password  string `form:"password" json:"password" bindind:"required"`
	Email     string `gorm:"type:varchar(110);unique_index" form:"email" json:"email,omitempty" binding:"required"`
	Location  string `form:"location" json:"location,omitempty"`
    Avatar    string `form:"avatar" json:"avatar,omitempty"`
    BgImg     string `form:"bg_img" json:"bg_img,omitempty"`
    CreatedAt time.Time
    UpdatedAt time.Time
    DeletedAt time.Time
}

I've tried several different ways, but this way throws (pq: relation "users" does not exist). I have no related models, it's literally just that one model.

I've tried using...

func (user *User) BeforeCreate(scope *gorm.Scope) error {
	scope.SetColumn("ID", uuid.NewV4())
	return nil
}

Along with a uuid lib, but had no luck with that either.

答案1

得分: 14

对于postgresql,我做了以下操作:

  • 使用go get github.com/google/uuid命令安装了github.com/google/uuid库。
  • 使用uuid.UUID作为类型(来自"github.com/google/uuid"),例如:
    ID       uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4()"`
    
  • 为Postgres数据库添加了uuid-ossp扩展,例如:
    CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
    
  • 当调用DB的Create()方法时,uuid会自动生成。

更新:pg14+ gen_random_uuid()

(正如Doron Segal的评论中提到的)

pg 14内置了函数gen_random_uuid()来生成uuid v4,例如:

创建表:

create table uuid_test (uid text default gen_random_uuid());

插入一行:

insert into uuid_test(uid) values (DEFAULT);

然后uid列会自动生成。


类似地,在go中,你可以将该函数作为默认值使用,例如:

ID       uuid.UUID `gorm:"type:uuid;default:gen_random_uuid()"`

顺便说一下,gen_random_uuid()函数目前仅支持uuid v4,如果要使用其他版本,仍然需要uuid-ossp扩展。

英文:

For postgresql, here is what I did:

  • go get github.com/google/uuid
  • Use uuid.UUID (from "github.com/google/uuid"), as type,
    e.g
    <pre>ID uuid.UUID gorm:&quot;type:uuid;default:uuid_generate_v4()&quot;</pre>
  • Add uuid-ossp extension for postgres database,
    e.g
    <pre>CREATE EXTENSION IF NOT EXISTS "uuid-ossp";</pre>
  • Then, when you call DB's Create() method, the uuid is generated automatically.

Update: pg14+ gen_random_uuid()

(as mentioned in Doron Segal's comment)

pg 14 has built-in function gen_random_uuid() to generate uuid v4, e.g:

create table:
> create table uuid_test (uid text default gen_random_uuid());

insert a row:

> insert into uuid_test(uid) values (DEFAULT);

Then uid column is generated automatically.


Similiar, in go you can use the function as defaul value I think, e.g:
> ID uuid.UUID gorm:&quot;type:uuid;default:gen_random_uuid()&quot;


BTW, the gen_random_uuid() function only support uuid v4 now, to use other versions, you still need uuid-ossp extension.

答案2

得分: 13

原来我试图将UUID存储为错误的类型,我原来的写法是...

func (user *User) BeforeCreate(scope *gorm.Scope) error {
    scope.SetColumn("ID", uuid.NewV4())
    return nil
}

但实际上应该是...

func (user *User) BeforeCreate(scope *gorm.Scope) error {
    scope.SetColumn("ID", uuid.NewV4().String())
    return nil
}
英文:

Turns out I was trying to store the UUID as the wrong type, I was doing...

func (user *User) BeforeCreate(scope *gorm.Scope) error {
	scope.SetColumn(&quot;ID&quot;, uuid.NewV4())
	return nil
}

When it needed to be...

func (user *User) BeforeCreate(scope *gorm.Scope) error {
    scope.SetColumn(&quot;ID&quot;, uuid.NewV4().String())
    return nil
}

答案3

得分: 7

这是我对 Gorm v1.21 的解决方案:

go get gorm.io/gorm
go get gorm.io/driver/postgres
go get github.com/google/uuid
import (
  "gorm.io/gorm"
  "github.com/google/uuid"
)

type User struct {
  Id string `gorm:"primaryKey"`
}

// 注意:如果函数签名不包括 `*gorm.DB` 和 `error`,Gorm 将会失败

func (user *User) BeforeCreate(tx *gorm.DB) (err error) {
  // UUID 版本 4
  user.Id = uuid.NewString()
  return
}

注意事项:

  1. 对于 Google UUID 包,uuid.New()uuid.NewString() 方法使用的是 UUID 版本 4。虽然在文档(http://pkg.go.dev/github.com/google/uuid)中没有明确说明,但通过查看源代码,可以看到这些方法是对 uuid.NewRandom() 的封装,而 uuid.NewRandom() 被声明为 UUID 版本 4。

  2. 虽然有些人推荐使用 Satori UUID 包(https://github.com/satori/go.uuid),但基准测试显示它的性能比 Google UUID 包低 3.3 倍(https://gist.github.com/mattes/69a4ab7027b9e8ee952b5843e7ca6955)。

英文:

This was my solution for Gorm v1.21

go get gorm.io/gorm
go get gorm.io/driver/postgres
go get github.com/google/uuid
import (
  &quot;gorm.io/gorm&quot;
  &quot;github.com/google/uuid&quot;
)

type User struct {
  Id string `gorm:&quot;primaryKey&quot;`
}

// Note: Gorm will fail if the function signature
//  does not include `*gorm.DB` and `error`

func (user *User) BeforeCreate(tx *gorm.DB) (err error) {
  // UUID version 4
  user.Id = uuid.NewString()
  return
}

Notes:

  1. For the Google UUID package, the methods uuid.New() and uuid.NewString() use UUID version 4. This is not clearly stated in the documentation (http://pkg.go.dev/github.com/google/uuid), but by looking into the source code, you can see that these are wrappers around uuid.NewRandom() which is stated as being UUID version 4.

  2. While some recommend the Satori UUID package (https://github.com/satori/go.uuid), benchmarks show that it has 3.3x lower performance than the Google UUID package
    (https://gist.github.com/mattes/69a4ab7027b9e8ee952b5843e7ca6955)

答案4

得分: 5

为此,您将需要gormgo.uuid

go get github.com/jinzhu/gorm

go get github.com/satori/go.uuid

尝试创建自己的模型基础模型,以替代gorm.Model,如下所示:

type Base struct {
 ID         string     `sql:"type:uuid;primary_key;default:uuid_generate_v4()"`
 CreatedAt  time.Time  `json:"created_at"`
 UpdatedAt  time.Time  `json:"updated_at"`
 DeletedAt  *time.Time `sql:"index" json:"deleted_at"`
}

然后,您可以使用在创建任何记录之前调用的方法来填充此字段,如下所示:

func (base *Base) BeforeCreate(scope *gorm.Scope) error {
 id, err := uuid.NewV4()
 if err != nil {
   return err
 }
 return scope.SetColumn("ID", uuid.String())
}

因此,对于您的特定情况,您将拥有:

type User struct {
    Base
    FirstName string `form:"first_name" json:"first_name,omitempty"`
    LastName  string `form:"last_name" json:"last_name,omitempty"`
    Password  string `form:"password" json:"password" bindind:"required"`
    Email     string `gorm:"type:varchar(110);unique_index" form:"email" json:"email,omitempty" binding:"required"`
    Location  string `form:"location" json:"location,omitempty"`
    Avatar    string `form:"avatar" json:"avatar,omitempty"`
    BgImg     string `form:"bg_img" json:"bg_img,omitempty"`
}

有关更多详细信息,请参阅此处

英文:

For this you will need gorm and go.uuid

go get github.com/jinzhu/gorm

go get github.com/satori/go.uuid

Try creating your own model base model in place of gorm.Model like so:

type Base struct {
 ID         string     `sql:&quot;type:uuid;primary_key;default:uuid_generate_v4()&quot;`
 CreatedAt  time.Time  `json:&quot;created_at&quot;`
 UpdatedAt  time.Time  `json:&quot;updated_at&quot;`
 DeletedAt  *time.Time `sql:&quot;index&quot; json:&quot;deleted_at&quot;`
}

You would then populate this field using a method called before creation of any record, like so:

func (base *Base) BeforeCreate(scope *gorm.Scope) error {
 id, err := uuid.NewV4()
 if err != nil {
   return err
 }
 return scope.SetColumn(&quot;ID&quot;, uuid.String())
}

Therefore, for your particular case, you would have:

type User struct {
    Base
    FirstName string `form:&quot;first_name&quot; json:&quot;first_name,omitempty&quot;`
    LastName  string `form:&quot;last_name&quot; json:&quot;last_name,omitempty&quot;`
    Password  string `form:&quot;password&quot; json:&quot;password&quot; bindind:&quot;required&quot;`
    Email     string `gorm:&quot;type:varchar(110);unique_index&quot; form:&quot;email&quot; json:&quot;email,omitempty&quot; binding:&quot;required&quot;`
    Location  string `form:&quot;location&quot; json:&quot;location,omitempty&quot;`
    Avatar    string `form:&quot;avatar&quot; json:&quot;avatar,omitempty&quot;`
    BgImg     string `form:&quot;bg_img&quot; json:&quot;bg_img,omitempty&quot;`
}

More details on this can be found here

答案5

得分: 1

错误 (pq: relation "users" does not exist) 通常意味着数据库中不存在表 users。这与两个模型之间的关系无关。

所以基本上,你首先需要在数据库中创建该表(或按照 @Apin 的建议自动迁移数据库)。然后尝试重新运行相同的代码。

英文:

The error (pq: relation &quot;users&quot; does not exist) usually means that, the table users does not exists in the database. It has nothing to do with the relationship between two models.

So basically, You first need to create the table in the database (Or auto migrate the database As per @Apin suggest). And try to re-run the same code.

答案6

得分: 0

以下是翻译好的内容:

这些方法在我使用 gorm v1.21 时都没有起作用。
以下是我的解决方案。请注意,我使用了 satori/go.uuid 库来生成 UUID,但是使用 google 的库的代码几乎相同。

type UUIDBaseModel struct {
    ID        uuid.UUID       `gorm:"primary_key" json:"id"`
    CreatedAt time.Time  `json:"created_at"`
    UpdatedAt time.Time  `json:"updated_at"`
    DeletedAt *time.Time `sql:"index" json:"deleted_at"`
}

func (base *UUIDBaseModel) BeforeCreate(tx *gorm.DB) error {
    uuid := uuid.NewV4().String()
    tx.Statement.SetColumn("ID", uuid)
    return nil
}
英文:

None of these worked for me using gorm v1.21.
Here was my solution. Note that I'm using the satori/go.uuid library for generating UUID, but code with google's library is near identical.

type UUIDBaseModel struct {
	ID        uuid.UUID       `gorm:&quot;primary_key&quot; json:&quot;id&quot;`
	CreatedAt time.Time  `json:&quot;created_at&quot;`
	UpdatedAt time.Time  `json:&quot;updated_at&quot;`
	DeletedAt *time.Time `sql:&quot;index&quot; json:&quot;deleted_at&quot;`
}

func (base *UUIDBaseModel) BeforeCreate(tx *gorm.DB) error {
	uuid := uuid.NewV4().String()
	tx.Statement.SetColumn(&quot;ID&quot;, uuid)
	return nil
}

答案7

得分: 0

现在我使用的是 Gorm 2.0,这个方法有效:

go get github.com/satori/go.uuid 
type Tablename struct {
 ID         string     `sql:"type:uuid;primary_key;default:uuid_generate_v4()"`
 }
英文:

Now I used Gorm 2.0 and this worked:

go get github.com/satori/go.uuid 
type Tablename struct {
 ID         string     `sql:&quot;type:uuid;primary_key;default:uuid_generate_v4()&quot;`
 }

答案8

得分: 0

使用MySQL 8.0和gorm(gorm.io/driver/mysql v1.5.0和gorm.io/gorm v1.25.1):

type ModelUUID struct {
	ID        string         `gorm:"type:binary(16);column:id;primaryKey;default:(UUID_TO_BIN(UUID(), 1));" json:"id" validate:"required"`
	CreatedAt time.Time      `json:"createdAt"`
	UpdatedAt time.Time      `json:"-"`
	DeletedAt gorm.DeletedAt `json:"-" gorm:"index" swaggerignore:"true"`
}
英文:

With MySQL 8.0 and gorm (gorm.io/driver/mysql v1.5.0 and gorm.io/gorm v1.25.1):

type ModelUUID struct {
	ID        string         `gorm:&quot;type:binary(16);column:id;primaryKey;default:(UUID_TO_BIN(UUID(), 1));&quot; json:&quot;id&quot; validate:&quot;required&quot;`
	CreatedAt time.Time      `json:&quot;createdAt&quot;`
	UpdatedAt time.Time      `json:&quot;-&quot;`
	DeletedAt gorm.DeletedAt `json:&quot;-&quot; gorm:&quot;index&quot; swaggerignore:&quot;true&quot;`
}

huangapple
  • 本文由 发表于 2016年4月8日 04:26:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/36486511.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定