扫码一下
查看教程更方便
在创建、更新记录时,gorm 会通过 upsert 自动保存关联及其引用记录。
user := user{
name: "jinzhu",
billingaddress: address{address1: "billing address - address 1"},
shippingaddress: address{address1: "shipping address - address 1"},
emails: []email{
{email: "jinzhu@example.com"},
{email: "jinzhu-2@example.com"},
},
languages: []language{
{name: "zh"},
{name: "en"},
},
}
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)
如果我们想要更新关联的数据,应该使用 fullsaveassociations
模式:
db.session(&gorm.session{fullsaveassociations: true}).updates(&user)
// ...
// insert into "addresses" (address1) values ("billing address - address 1"), ("shipping address - address 1") on duplicate key set address1=values(address1);
// 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 set email=values(email);
// ...
若要在创建、更新时跳过自动保存,我们可以使用 select 或 omit,例如:
user := user{
name: "jinzhu",
billingaddress: address{address1: "billing address - address 1"},
shippingaddress: address{address1: "shipping address - address 1"},
emails: []email{
{email: "jinzhu@example.com"},
{email: "jinzhu-2@example.com"},
},
languages: []language{
{name: "zh"},
{name: "en"},
},
}
db.select("name").create(&user)
// insert into "users" (name) values ("jinzhu", 1, 2);
db.omit("billingaddress").create(&user)
// skip create billingaddress when creating a user
db.omit(clause.associations).create(&user)
// skip all associations when creating a user
注意
: 对于many2many
关联,gorm 在创建连接表引用之前,会先 upsert 关联。如果你想跳过关联的 upsert,你可以这样做:db.omit("languages.*").create(&user)
下面的代码将跳过创建关联及其引用
db.omit("languages").create(&user)
user := user{
name: "jinzhu",
billingaddress: address{address1: "billing address - address 1", address2: "addr2"},
shippingaddress: address{address1: "shipping address - address 1", address2: "addr2"},
}
// 创建 user 及其 billingaddress、shippingaddress
// 在创建 billingaddress 时,仅使用其 address1、address2 字段,忽略其它字段
db.select("billingaddress.address1", "billingaddress.address2").create(&user)
db.omit("billingaddress.address2", "billingaddress.createdat").create(&user)
关联模式包含一些在处理关系时有用的方法
// 开始关联模式
var user user
db.model(&user).association("languages")
// `user` 是源模型,它的主键不能为空
// 关系的字段名是 `languages`
// 如果匹配了上面两个要求,会开始关联模式,否则会返回错误
db.model(&user).association("languages").error
查找所有匹配的关联记录
db.model(&user).association("languages").find(&languages)
查找带条件的关联
codes := []string{"zh-cn", "en-us", "ja-jp"}
db.model(&user).where("code in ?", codes).association("languages").find(&languages)
db.model(&user).where("code in ?", codes).order("code desc").association("languages").find(&languages)
为 many to many 、 添加新的关联;为 has one , belongs to 替换当前的关联
db.model(&user).association("languages").append([]language{languagezh, languageen})
db.model(&user).association("languages").append(&language{name: "de"})
db.model(&user).association("creditcard").append(&creditcard{number: "411111111111"})
用一个新的关联替换当前的关联
db.model(&user).association("languages").replace([]language{languagezh, languageen})
db.model(&user).association("languages").replace(language{name: "de"}, languageen)
如果存在,则删除源模型与参数之间的关系,只会删除引用,不会从数据库中删除这些对象。
db.model(&user).association("languages").delete([]language{languagezh, languageen})
db.model(&user).association("languages").delete(languagezh, languageen)
删除源模型与关联之间的所有引用,但不会删除这些关联
db.model(&user).association("languages").clear()
返回当前关联的计数
db.model(&user).association("languages").count()
// 条件计数
codes := []string{"zh-cn", "en-us", "ja-jp"}
db.model(&user).where("code in ?", codes).association("languages").count()
关联模式也支持批量处理,例如:
// 查询所有用户的所有角色
db.model(&users).association("role").find(&roles)
// 从所有 team 中删除 user a
db.model(&users).association("team").delete(&usera)
// 获取去重的用户所属 team 数量
db.model(&users).association("team").count()
// 对于批量数据的 `append`、`replace`,参数的长度必须与数据的长度相同,否则会返回 error
var users = []user{user1, user2, user3}
// 例如:现在有三个 user,append usera 到 user1 的 team,append userb 到 user2 的 team,append usera、userb 和 userc 到 user3 的 team
db.model(&users).association("team").append(&usera, &userb, &[]user{usera, userb, userc})
// 重置 user1 team 为 usera,重置 user2 的 team 为 userb,重置 user3 的 team 为 usera、 userb 和 userc
db.model(&users).association("team").replace(&usera, &userb, &[]user{usera, userb, userc})
你可以在删除记录时通过 select 来删除具有 has one
、has many
、many2many
关系的记录,例如:
// 删除 user 时,也删除 user 的 account
db.select("account").delete(&user)
// 删除 user 时,也删除 user 的 orders、creditcards 记录
db.select("orders", "creditcards").delete(&user)
// 删除 user 时,也删除用户所有 has one/many、many2many 记录
db.select(clause.associations).delete(&user)
// 删除 users 时,也删除每一个 user 的 account
db.select("account").delete(&users)
注意
: 只有当记录的主键不为空时,关联才会被删除,gorm 会使用这些主键作为条件来删除关联记录
// doesn't work
db.select("account").where("name = ?", "jinzhu").delete(&user{})
// 会删除所有 name=`jinzhu` 的 user,但这些 user 的 account 不会被删除
db.select("account").where("name = ?", "jinzhu").delete(&user{id: 1})
// 会删除 name = `jinzhu` 且 id = `1` 的 user,并且 user `1` 的 account 也会被删除
db.select("account").delete(&user{id: 1})
// 会删除 id = `1` 的 user,并且 user `1` 的 account 也会被删除
标签 | 描述 |
---|---|
foreignkey | 指定当前模型的列作为连接表的外键 |
references | 指定引用表的列名,其将被映射为连接表外键 |
polymorphic | 指定多态类型,比如模型名 |
polymorphicvalue | 指定多态值、默认表名 |
many2many | 指定连接表表名 |
joinforeignkey | 指定连接表的外键列名,其将被映射到当前表 |
joinreferences | 指定连接表的外键列名,其将被映射到引用表 |
constraint | 关系约束,例如:onupdate、ondelete |