定义模型
将表映射到结构体
对于每个表,您都需要定义一个相应的 Go 结构体(模型)。Bun 将导出的结构体字段映射到表列,并忽略未导出的字段。
type User struct {
bun.BaseModel `bun:"table:users,alias:u"`
ID int64 `bun:"id,pk,autoincrement"`
Name string `bun:"name,notnull"`
email string // unexported fields are ignored
}
结构体标签
Bun 使用合理的默认值来生成名称并推断类型,但您可以使用以下结构体标签来覆盖默认值。
标签 | 注释 |
---|---|
bun.BaseModel `bun:"table:table_name"` | 覆盖默认表名。 |
bun.BaseModel `bun:"alias:table_alias"` | 覆盖默认表别名。 |
bun.BaseModel `bun:"select:view_name"` | 覆盖 SELECT 查询的表名。 |
bun:"-" | 忽略该字段。 |
bun:"column_name" | 覆盖默认列名。 |
bun:"alt:alt_name" | 备用列名。在迁移期间很有用。 |
bun:",pk" | 将列标记为主键并应用 notnull 选项。支持多个/复合主键。 |
bun:",autoincrement" | 将列标记为 PostgreSQL 中的 serial,MySQL 中的 autoincrement,以及 MSSQL 中的 identity。还应用 nullzero 选项。 |
bun:"type:uuid" | 覆盖默认 SQL 类型。 |
bun:"default:gen_random_uuid()" | 告诉 CreateTable 设置 DEFAULT 表达式。 |
bun:",notnull" | 告诉 CreateTable 添加 NOT NULL 约束。 |
bun:",unique" | 告诉 CreateTable 添加唯一约束。 |
bun:",unique:group_name" | 一组列的唯一约束。 |
bun:",nullzero" | 将 Go 零值编组为 SQL NULL 或 DEFAULT (如果支持)。 |
bun:",scanonly" | 仅使用此字段扫描查询结果,并在 SELECT/INSERT/UPDATE/DELETE 中忽略。 |
bun:",array" | 使用 PostgreSQL 数组。 |
bun:",json_use_number" | 使用 json.Decoder.UseNumber 解码 JSON。 |
bun:",msgpack" | 使用 MessagePack 编码/解码数据。 |
DeletedAt time.Time `bun:",soft_delete"` | 在模型上启用软删除。 |
表名
Bun 通过下划线将结构体名称生成表名和别名。它还将表名复数化,例如,结构体 ArticleCategory
获取表名 article_categories
和别名 article_category
。
要覆盖生成的名称和别名
type User struct {
bun.BaseModel `bun:"table:myusers,alias:u"`
}
要为 SELECT
查询指定不同的表名
type User struct {
bun.BaseModel `bun:"select:users_view,alias:u"`
}
ModelTableExpr
使用 ModelTableExpr
方法,您可以覆盖结构体表名,但不能覆盖别名。ModelTableExpr
应始终使用相同的表别名,例如
type User struct {
bun.BaseModel `bun:"table:myusers,alias:u"`
}
// Good.
db.NewSelect().Model(&User{}).ModelTableExpr("all_users AS u")
db.NewSelect().Model(&User{}).ModelTableExpr("deleted_users AS u")
// Bad.
db.NewSelect().Model(&User{}).ModelTableExpr("all_users AS user")
db.NewSelect().Model(&User{}).ModelTableExpr("deleted_users AS deleted")
列名
Bun 通过下划线将结构体字段名称生成列名。例如,结构体字段 UserID
获取列名 user_id
。
要覆盖生成的列名
type User struct {
Name string `bun:"myname"`
}
SQL 命名约定
使用 snake_case 标识符作为表名和列名。如果您遇到虚假的 SQL 解析器错误,请尝试用双引号(MySQL 为反引号)引起来标识符,以检查问题是否消失。
警告
不要使用 SQL 关键字(例如order
、user
)作为标识符。
警告
不要使用区分大小写的名称,因为此类名称将折叠为小写,例如,UserOrders
变为 userorders
。
列类型
Bun 从结构体字段类型生成列类型。例如,Go 类型 string
被转换为 SQL 类型 varchar
。
要覆盖生成的列类型
type User struct {
ID int64 `bun:"type:integer"`
}
NULL
要表示 SQL NULL
,您可以使用指针或 sql.Null*
类型
type Item struct {
Active *bool
// or
Active sql.NullBool
}
例如
(*bool)(nil)
和sql.NullBool{}
表示NULL
。(*bool)(false)
和sql.NullBool{Valid: true}
表示FALSE
。(*bool)(true)
和sql.NullBool{Valid: true, Value: true}
表示TRUE
。
Go 零值和 NULL
要将 Go 零值编组为 NULL
,请使用 nullzero
标签
type User struct {
Name string `bun:",nullzero"`
}
DEFAULT
要指定默认 SQL 表达式,请使用 nullzero
、notnull
和 default
标签的组合
type User struct {
Name string `bun:",nullzero,notnull,default:'unknown'"`
}
err := db.NewCreateTable().Model((*User)(nil)).Exec(ctx)
CREATE TABLE users (
name text NOT NULL DEFAULT 'unknown'
);
自动时间戳
使用以下代码在 INSERT
上自动设置创建和更新时间
type User struct {
CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"`
UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"`
}
如果您不想设置更新时间,请使用 bun.NullTime
type User struct {
CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"`
UpdatedAt bun.NullTime
}
您还可以使用 钩子 设置结构体字段
var _ bun.BeforeAppendModelHook = (*User)(nil)
func (u *User) BeforeAppendModel(ctx context.Context, query bun.Query) error {
switch query.(type) {
case *bun.InsertQuery:
u.CreatedAt = time.Now()
case *bun.UpdateQuery:
u.UpdatedAt = time.Now()
}
return nil
}
扩展模型
您可以使用 extend
标签选项向现有模型添加/删除字段。新模型将继承原始模型的表名和别名。
type UserWithCount struct {
User `bun:",extend"`
Name string `bun:"-"` // remove this field
AvatarCount int // add a new field
}
嵌入结构体
Bun 允许使用前缀将模型嵌入到另一个模型中,例如
type Role struct {
Name string
Users Permissions `bun:"embed:users_"`
Profiles Permissions `bun:"embed:profiles_"`
Roles Permissions `bun:"embed:roles_"`
}
type Permissions struct {
View bool
Create bool
Update bool
Delete bool
}
上面的代码生成以下表
CREATE TABLE roles (
name TEXT,
users_view BOOLEAN,
users_create BOOLEAN,
users_update BOOLEAN,
users_delete BOOLEAN,
profiles_view BOOLEAN,
profiles_create BOOLEAN,
profiles_update BOOLEAN,
profiles_delete BOOLEAN,
roles_view BOOLEAN,
roles_create BOOLEAN,
roles_update BOOLEAN,
roles_delete BOOLEAN
);