V2
关联查询
// user
type TbUser struct {
dbUtils.FieldsModel
ID uint `gorm:"primarykey"`
CompanyID int
Name string
Tag string
Age int
}
type TbCompany struct {
dbUtils.FieldsModel
Address string
Name string
}
type TbCard struct {
ID uint `gorm:"primarykey"`
UserID uint
Number int
}
type TbLanguage struct {
ID uint `gorm:"primarykey"`
Name string
}
// 当使用 GORM 的 AutoMigrate 为 User 创建表时,GORM 会自动创建连接表。这里只是展示
type TbUserLanguage struct {
LanguageId uint
UserId uint
}
type FieldsModel struct {
ID uint `gorm:"primarykey"`
CreatedAt int64 `gorm:"autoCreateTime:milli;type:bigint(13);unsigned;comment:创建时间" json:"created_at"`
UpdatedAt int64 `gorm:"autoUpdateTime:milli;type:bigint(13);unsigned;comment:修改时间" json:"updated_at"`
DeletedAt soft_delete.DeletedAt `gorm:"type:bigint(13);unsigned;comment:删除时间" json:"deleted_at"`
}
// 一个用户属于一个公司
// user.company_id -> company.id
func TestPageParamBelongsTo(t *testing.T) {
type User struct {
TbUser
Company TbCompany
}
res := &[]User{}
err := DB.Preload(clause.Associations).Find(res).Error
fmt.Println(err)
}
// 一个用户有一张唱片
// user.id -> card.user_id
func TestPageParamHasOne(t *testing.T) {
type User struct {
TbUser
Card TbCard
}
res := &[]User{}
err := DB.PreloadAll().Find(res).Error
fmt.Println(err)
}
// 一个用户有多张唱片
// user.id -> []card.user_id
func TestPageParamHasMany(t *testing.T) {
type User struct {
TbUser
Card []TbCard
}
res := &[]User{}
err := DB.PreloadAll().Find(res).Error
fmt.Println(err)
}
// `user_languages` 是连接表
func TestPageParamManyToMany(t *testing.T) {
type Language struct {
TbLanguage
Users []*TbUser `gorm:"many2many:user_languages;"`
}
type User struct {
TbUser
Languages []*Language `gorm:"many2many:user_languages;"`
}
// 正向: 一个人会多种语言 user <- []language
// user.id -> user_languages.user_id,[]language_id -> language.id
func() {
res := &[]User{}
err := DB.PreloadAll().Find(res).Error
fmt.Println(err)
}()
// 反向: 一群人会一种语言 language <- []user
// language.id -> user_languages.language_id,[]user_id -> user.id
func() {
res := &[]Language{}
err := DB.PreloadAll().Find(res).Error
fmt.Println(err)
}()
}
Preload 预加载
加载层级
层级递归查询
例 公司部门下属,家庭父子关系。
// 一个iss:https://github.com/go-gorm/gorm/issues/4027
// 官方递归:https://gorm.io/docs/has_many.html#Self-Referential-Has-Many
type Person struct {
ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()" form:"id" json:"id"`
Name string `json:"name"`
ParentID *string `json:"parent_id" gorm:"type:uuid"`
Children []Person `gorm:"foreignKey:ParentID" json:"children"`
}
func TestChildren(t *testing.T) {
// 注意:ParentID 是 `*string` 类型,查询没有问题。
// 关联添加的时候必须给指针类型(非指针插入会报错),使用指针会关联插入。
data := Person{
Name: "a1",
Children: []Person{
{
Name: "a2",
Children: []Person{
{
Name: "a3",
},
},
},
},
}
DB.Create(&data)
var result Person
// 第一个 Preload 加载其他的关联
// 第二个 Preload 加载 Children 的关系
DB.Preload(clause.Associations).Preload("Children." + clause.Associations).Find(&result)
}
运行结果
// INSERT INTO "person" (name, parent_id) VALUES ("a1", "");
// INSERT INTO "person" (name, parent_id) VALUES ("a2", "da185c9c-1717-4720-9fd3-4cc26fc2659d");
// INSERT INTO "person" (name, parent_id) VALUES ("a3", "e1cea70b-6eb4-4b83-8500-7a87a65c5fd1");
// 这个是倒叙的
// SELECT * FROM "person" WHERE "person"."parent_id" = 'e1cea70b-6eb4-4b83-8500-7a87a65c5fd1'
// SELECT * FROM "person" WHERE "person"."parent_id" = 'da185c9c-1717-4720-9fd3-4cc26fc2659d'
// SELECT * FROM "person"
相关社区
- go-gorm/datatypes - 支持 json、jsonMap、date类型。
``go type Available struct { Use bool
json:”use”Reason string
json:”reason”` }
// Scan scan value into Jsonb, implements sql.Scanner interface func (a *Available) Scan(value interface{}) error { json return nil }
func (a Available) Value() (driver.Value, error) {
return fmt.Sprintf((%t,"%s")
, a.Use, a.Reason), nil
}
- [pq](https://github.com/lib/pq) - `BoolArray` `ByteaArray` `Float32Array` `Int32Array` `StringArray` `GenericArray 自定义类型数组` 等等数组类型。帮助我们使用 postgreSQL 的数据类型。
```go
// 使用 GenericArray 完成 []AvailableArray 结构
type AvailableArray []Available
func (a *AvailableArray) Scan(src interface{}) error {
return pq.GenericArray{A: a}.Scan(src)
}
func (a AvailableArray) Value() (driver.Value, error) {
if a == nil {
return "{}", nil
}
return pq.GenericArray{A: a}.Value()
}
func (a AvailableArray) MarshalJSON() ([]byte, error) {
res := make([]Available, 0)
if a != nil {
res = a
}
return json.Marshal(res)
}
- gorm-extra-clause-plugin - 支持 postgreSQL 的 WITH (CTE)语法。
V1 已过时
文档:官方、中文文档、tag 介绍
注意:以下是一些需要特别注意的:
debug:
// 启用Logger,显示详细日志
db.LogMode(true)
// 禁用日志记录器,不显示任何日志
db.LogMode(false)
// 调试单个操作,显示此操作的详细日志
db.Debug().Where("name = ?", "jinzhu").First(&User{})
事务:
// 开始事务
tx := db.Begin()
// 在事务中做一些数据库操作(从这里必须使用'tx',而不是'db')
tx.Create(...)
// ...
// 发生错误时回滚事务
tx.Rollback()
// 或提交事务
tx.Commit()