目标
看了gorm文档,但是对多对多等关系有一些疑惑,官方也没有提供对象关系实现的代码,所以有了这篇文章.这篇文章解决以下问题:
- 代码实现并掌握使用"关联"使用方法
- 理解Belong to,has one,has many,many to many的含义和区别
没有对gorm其他部分做深入的探讨
过程
以下实现步骤都为"建模","迁移","数据对象写入","查询"四部分
Belongs To
实现:
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// `User` 属于 `Company`,`CompanyID` 是外键
type User struct {
gorm.Model
Name string
CompanyID int
Company Company
}
type Company struct {
ID int
Name string
Users []User
}
func main() {
db, err := gorm.Open(sqlite.Open("belongTo.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&User{})
user := User{
Name: "Tom",
Company: Company{
Name: "my Com",
},
}
//db.Create(&user)
// BEGIN TRANSACTION;
// INSERT INTO "addresses" (address1) VALUES ("Billing Address - Address 1"), ("Shipping Address - Address 1") ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "users" (name,billing_address_id,shipping_address_id) VALUES ("jinzhu", 1, 2);
// INSERT INTO "emails" (user_id,email) VALUES (111, "jinzhu@example.com"), (111, "jinzhu-2@example.com") ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "languages" ("name") VALUES ('ZH'), ('EN') ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "user_languages" ("user_id","language_id") VALUES (111, 1), (111, 2) ON DUPLICATE KEY DO NOTHING;
// COMMIT;
db.Save(&user)
var getUser User
rs := db.Preload("Company").Last(&getUser)
fmt.Println(rs)
//反向实现has many
//company := Company{
// Name: "has many",
// Users: []User{
// {
// Name: "zhangsan",
// },
// {
// Name: "lisi",
// },
// },
//}
//db.Save(&company)
var getCompany Company
rs = db.Preload("Users").Last(&getCompany)
fmt.Println(rs)
fmt.Println(getCompany)
}
Has one
实现:
package main
import (
"encoding/json"
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// User 有一张 CreditCard,CreditCardID 是外键
type User struct {
gorm.Model
CreditCard CreditCard
}
type CreditCard struct {
gorm.Model
Number string
UserID uint
}
func main() {
db, err := gorm.Open(sqlite.Open("hasOne.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&User{})
db.AutoMigrate(&CreditCard{})
user := User{
CreditCard: CreditCard{
Number: "10076",
},
}
db.Create(&user)
var getUser User
rs := db.Preload("CreditCard").Last(&getUser)
fmt.Println(rs)
byt, _ := json.Marshal(getUser)
fmt.Println(string(byt))
//var getUser2 User
var card CreditCard
db.Model(&getUser).Association("CreditCard").Find(&card)
fmt.Println()
}
Has Many
package main
import (
"encoding/json"
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// User 有多张 CreditCard,UserID 是外键
type User struct {
gorm.Model
CreditCards []CreditCard
}
type CreditCard struct {
gorm.Model
Number string
UserID uint
}
func main() {
db, err := gorm.Open(sqlite.Open("hasMany.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&User{})
db.AutoMigrate(&CreditCard{})
user := User{
CreditCards: []CreditCard{
{
Number: "10000",
},
{
Number: "10001",
},
},
}
db.Create(&user)
var getUser User
rs := db.Preload("CreditCards").Last(&getUser)
fmt.Println(rs)
byt, _ := json.Marshal(getUser)
fmt.Println(string(byt))
}
Many To Many
package main
import (
"encoding/json"
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// User 拥有并属于多种 language,`user_languages` 是连接表
type User struct {
gorm.Model
Languages []Language `gorm:"many2many:user_languages;"`
}
type Language struct {
gorm.Model
Name string
Users []*User `gorm:"many2many:user_languages;"`
}
func main() {
db, err := gorm.Open(sqlite.Open("manyToMany.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&User{})
db.AutoMigrate(&Language{})
user1 := User{
Languages: []Language{
{
Name: "chinese",
},
{
Name: "jpn",
},
},
}
user2 := User{
Languages: []Language{
{
Name: "chinese",
},
{
Name: "jpn",
},
},
}
db.Create(&user1)
db.Create(&user2)
var getUser User
rs := db.Preload("Languages").Last(&getUser)
fmt.Println(rs)
byt, _ := json.Marshal(getUser)
fmt.Println(string(byt))
var getLanguage Language
rs = db.Preload("Users").Last(&getLanguage)
fmt.Println(rs)
byt, _ = json.Marshal(getLanguage)
fmt.Println(string(byt))
}
总结:
belong to 是和 has one和has many 的反向实现,实际使用根据需要拉取关联对象,在belong to部分也做了反向实现
many to many 是 has many的相互关系,可以通过关联表来实现
参考:
下面文章里搜到了比较好的总结,粘贴如下:
belongs_to # 一对多,与 has_many,has_one 套用
has_one # 一对一
has_many # 一对多的另外一方
has_and_belongs_to_many # 多对多