英文:
How can i add enum in gorm?
问题
我正在编写 PostgreSQL 表模式。
type TestTable struct {
ID int `gorm:"column:id;primaryKey;autoIncrement"`
CarType string `gorm:"column:car_type"`
}
那么我该如何将 "SEDAN"、"HATCHBACK"、"MINIVAN" 等车型添加为 enum 数据类型呢?
英文:
I am writing PostgreSQL table schema.
type TestTable struct {
ID int `gorm:"column:id;primaryKey;autoIncrement"`
CarType string `gorm:"column:car_type"`
}
So how can i add car types like "SEDAN", "HATCHBACK", "MINIVAN" as enum data type
答案1
得分: 22
假设您正在使用GORM与PostgreSQL。首先,在您的数据库中创建一个类型。
CREATE TYPE car_type AS ENUM (
'SEDAN',
'HATCHBACK',
'MINIVAN'
);
然后,您需要定义以下模型:
import "database/sql/driver"
type carType string
const (
SEDAN carType = "SEDAN"
HATCHBACK carType = "HATCHBACK"
MINIVAN carType = "MINIVAN"
)
func (ct *carType) Scan(value interface{}) error {
*ct = carType(value.([]byte))
return nil
}
func (ct carType) Value() (driver.Value, error) {
return string(ct), nil
}
type MyTable struct {
gorm.Model
CarType carType `gorm:"type:car_type"`
}
func (MyTable) TableName() string {
return "my_table"
}
对于MySQL用户,请添加结构标签gorm:
或sql:
,这样您就不必运行原始查询来在数据库中创建枚举。
CarType carType `gorm:"type:enum('SEDAN', 'HATCHBACK', 'MINIVAN');column:car_type"`
或者
CarType carType `sql:"type:ENUM('SEDAN', 'HATCHBACK', 'MINIVAN')" gorm:"column:car_type"`
英文:
Assuming you are using GORM with PostgreSQL. First in your database create a type.
CREATE TYPE car_type AS ENUM (
'SEDAN',
'HATCHBACK',
'MINIVAN');
Then you will need to define the following model:
import "database/sql/driver"
type carType string
const (
SEDAN carType = "SEDAN"
HATCHBACK carType = "HATCHBACK"
MINIVAN carType = "MINIVAN"
)
func (ct *carType) Scan(value interface{}) error {
*ct = carType(value.([]byte))
return nil
}
func (ct carType) Value() (driver.Value, error) {
return string(ct), nil
}
type MyTable struct {
gorm.Model
CarType carType `gorm:"type:car_type"`
}
func (MyTable) TableName() string {
return "my_table"
}
Note for MySQL users, you can add struct tag gorm:
or sql:
so you don't have to run raw query to create enum in the database.
CarType carType `gorm:"type:enum('SEDAN', 'HATCHBACK', 'MINIVAN')";"column:car_type"`
OR
CarType carType `sql:"type:ENUM('SEDAN', 'HATCHBACK', 'MINIVAN')" gorm:"column:car_type"`
答案2
得分: 2
这里是一个不需要事先创建 SQL 类型的解决方案。你可以使用以下代码来定义你的字段标签:
type TestTable struct {
ID int `gorm:"column:id;primaryKey;autoIncrement"`
CarType carType `sql:"type:ENUM('SEDAN', 'HATCHBACK', 'MINIVAN')" gorm:"column:car_type"`
}
此外,你还需要为 carType
类型添加 Scan
和 Value
方法:
type carType string
const (
SEDAN carType = "SEDAN"
HATCHBACK carType = "HATCHBACK"
MINIVAN carType = "MINIVAN"
)
func (self *carType) Scan(value interface{}) error {
*self = carType(value.([]byte))
return nil
}
func (self carType) Value() (driver.Value, error) {
return string(self), nil
}
希望对你有帮助!
英文:
Edit: someone pointed out this only works with MySQL. I would take my answer down but someone using MySQL may find it helpful.
Here's an answer that doesn't require you to create a SQL type beforehand. My source for this solution was this github issue
For your field tag, use this:
type TestTable struct {
ID int `gorm:"column:id;primaryKey;autoIncrement"`
CarType carType `sql:"type:ENUM('SEDAN', 'HATCHBACK', 'MINIVAN')" gorm:"column:car_type"`
}
You'll also need to add the Scan and Value methods attached to your carType type.
type carType string
const (
SEDAN carType = "SEDAN"
HATCHBACK carType = "HATCHBACK"
MINIVAN carType = "MINIVAN"
)
func (self *carType) Scan(value interface{}) error {
*self = carType(value.([]byte))
return nil
}
func (self carType) Value() (driver.Value, error) {
return string(self), nil
}
答案3
得分: 1
在这方面,如果你决定采用稍微不同的方法:
你可以将枚举定义为int,并利用iota
。然后你可以使用代码生成器来创建SQL的Scaner/Valuer
,同时也可以创建JSON/文本表示。
例如:
https://github.com/dmarkham/enumer
英文:
on a side note- if you decide to go with slightly different approach:
you can define your enums as int, and leverage iota
. then you can use code generator to create sql Scaner/Valuer
but also json/text representations.
for example:
https://github.com/dmarkham/enumer
答案4
得分: 1
为了扩展Nick的答案,我在自动化方面添加了以下内容:
假设你有一个DBClient
结构体,你可以创建一个方法来创建这个car类型:
func (psqlClient *DBClient) CreateCarTypeEnum() error {
result := psqlClient.db.Exec("SELECT 1 FROM pg_type WHERE typname = 'car_type';")
switch {
case result.RowsAffected == 0:
if err := psqlClient.db.Exec("CREATE TYPE car_type AS ENUM ('SEDAN', 'HATCHBACK', 'MINIVAN');").Error; err != nil {
log.Error().Err(err).Msg("Error creating car_type ENUM")
return err
}
return nil
case result.Error != nil:
return result.Error
default:
return nil
}
}
英文:
in order to extend Nick's answer I am adding the following for automation:
Assuming you have DBClient
struct, you can create a method that creates this car type:
func (psqlClient *DBClient) CreateCarTypeEnum() error {
result := psqlClient.db.Exec("SELECT 1 FROM pg_type WHERE typname = 'car_type';")
switch {
case result.RowsAffected == 0:
if err := psqlClient.db.Exec("CREATE TYPE car_type AS ENUM ('SEDAN', 'HATCHBACK', 'MINIVAN');").Error; err != nil {
log.Error().Err(err).Msg("Error creating car_type ENUM")
return err
}
return nil
case result.Error != nil:
return result.Error
default:
return nil
}
}
答案5
得分: 1
就像你在SQL中编写的那样,你可以使用类型和添加任何你想要的数据类型,就像你在SQL中编写的那样。
type MyTable struct {
CarType string `gorm:"column:car_type;type:enum('SEDAN','HATCHBACK','MINIVAN')" json:"car_type"`
}
英文:
Just like you write in sql, you can use type and add whatever datatype you want like you write in sql.
type MyTable struct {
CarType string `gorm:"column:car_type;type:enum('SEDAN','HATCHBACK','MINIVAN')" json:"car_type"`
}
答案6
得分: 0
更新,不要使用sql:"car_type"
,而是使用gorm:"car_type"
。而且,你需要手动在数据库中创建自定义的枚举类型。
英文:
An update, it will not work with sql:"car_type"
instead use gorm:"car_type"
. That too once you have manually created the custom enum type into the database.
答案7
得分: -1
https://gorm.io/docs/data_types.html => 实现Scan和Value方法。
如果枚举是由protoc生成的,可以使用这个插件 https://github.com/yangyang5214/protoc-gen-gorm-serializer。
# task.proto
syntax = "proto3";
enum TaskStatus {
Unknown = 0;
Running = 1;
Exiting = 2;
Pending = 3;
}
# 生成 gorm-serializer.pb.go
protoc --proto_path=. --go_out=paths=source_relative:. --gorm-serializer_out=paths=source_relative:. task.proto
# 使用
type Task struct {
gorm.Model
Name string
Status example.TaskStatus `gorm:"type:int"`
}
英文:
https://gorm.io/docs/data_types.html => impl Scan & Value methods.
If enum is generated by protoc, can use this plugin
https://github.com/yangyang5214/protoc-gen-gorm-serializer .
# task.proto
syntax = "proto3";
enum TaskStatus {
Unknown = 0;
Running = 1;
Exiting = 2;
Pending = 3;
}
# gen gorm-serializer.pb.go
protoc --proto_path=. --go_out=paths=source_relative:. --gorm-serializer_out=paths=source_relative:. task.proto
# use
type Task struct {
gorm.Model
Name string
Status example.TaskStatus `gorm:"type:int"`
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论