GORM中db.FirstOrCreate与db.Where().FirstOrCreate的差异解析
关于GORM中
FirstOrCreate两种写法的差异解析 嗨,我来帮你把这两种写法的区别讲明白,核心就在于查询条件和创建时赋值的逻辑划分不同:
1. db.FirstOrCreate(&user, User{Name: "non_existing"})
这种写法里,第二个传入的结构体参数承担了两个角色:
- 首先作为查询匹配条件:GORM会用这个结构体里的非零字段(这里是
Name)去数据库查找匹配的记录 - 其次作为创建时的属性模板:如果数据库里找不到匹配的记录,GORM会直接用这个结构体的字段值来插入一条新记录
举你的例子:
未找到记录的情况:
db.FirstOrCreate(&user, User{Name: "non_existing"})
执行INSERT INTO "users" (name) VALUES ("non_existing");,最终user会被赋值为新创建的这条记录(包含自增ID和Name字段)
如果此时数据库里已经有一条Name="non_existing"的记录,GORM会直接把这条记录查询出来赋值给user,不会执行插入操作。
2. db.Where(User{Name: "Jinzhu"}).FirstOrCreate(&user)
这种写法把查询条件和创建赋值做了分离:
Where(User{Name: "Jinzhu"})里的内容仅仅是查询条件,GORM只会用它来查找匹配的记录- 当找不到匹配记录时,GORM会创建一个默认的空结构体实例(只有主键等自增字段会被数据库自动填充,其他字段会用零值,比如
Name会是空字符串,除非数据库字段有默认值),而不会把Where里的条件作为创建时的属性值
举个补充例子:如果执行db.Where(User{Name: "NewUser"}).FirstOrCreate(&user)且数据库里没有这条记录,最终插入的记录Name字段会是空(或者数据库默认值),而不是"NewUser"。
额外补充:如果想让Where条件同时作为创建赋值
如果想用Where的条件作为创建时的属性,需要结合Attrs()方法:
db.Where(User{Name: "Jinzhu"}).Attrs(User{Name: "Jinzhu"}).FirstOrCreate(&user)
或者用Assign()(区别是Assign()不管有没有找到记录,都会把属性赋值给user,而Attrs()只有在创建新记录时才会赋值)。
内容的提问来源于stack exchange,提问作者Asnim P Ansari
相关产品推荐
相关产品推荐

