Find to map
GORM 提供了灵活的数据查询,允许将结果扫描进(scanned into)map[string]interface{}
or []map[string]interface{}
,这对动态数据结构非常有用。
当使用 Find To Map
时,一定要在你的查询中包含 Model
或者 Table
,以此来显式地指定表名。 这能确保 GORM 正确的理解哪个表要被查询。
// 扫描第一个结果到 map with Model 中
result := map[string]interface{}{}
db.Model(&User{}).First(&result, "id = ?", 1)
// SQL: SELECT * FROM `users` WHERE id = 1 LIMIT 1
// 扫描多个结果到部分 maps with Table 中
var results []map[string]interface{}
db.Table("users").Find(&results)
// SQL: SELECT * FROM `users`
FirstOrInit
GORM 的 FirstOrInit
方法用于获取与特定条件匹配的第一条记录,如果没有成功获取,就初始化一个新实例。 这个方法与结构和map条件兼容,并且在使用 Attrs
和 Assign
方法时有着更多的灵活性。
// 如果没找到 name 为 "non_existing" 的 User,就初始化一个新的 User
var user User
db.FirstOrInit(&user, User{Name: "non_existing"})
// user -> User{Name: "non_existing"} if not found
// 检索名为 “jinzhu” 的 User
db.Where(User{Name: "jinzhu"}).FirstOrInit(&user)
// user -> User{ID: 111, Name: "Jinzhu", Age: 18} if found
// 使用 map 来指定搜索条件
db.FirstOrInit(&user, map[string]interface{}{"name": "jinzhu"})
// user -> User{ID: 111, Name: "Jinzhu", Age: 18} if found
使用 Attrs
进行初始化
当记录未找到,你可以使用 Attrs
来初始化一个有着额外属性的结构体。 这些属性包含在新结构中,但不在 SQL 查询中使用。
// 如果没找到对应条件的 User,会根据所给条件和额外属性初始化 User
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user)
// SQL: SELECT * FROM USERS WHERE name = 'non_existing' ORDER BY id LIMIT 1;
// user -> User{Name: "non_existing", Age: 20} if not found
// 如果名为 “Jinzhu” 的 User 被找到,`Attrs` 会被忽略
db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 20}).FirstOrInit(&user)
// SQL: SELECT * FROM USERS WHERE name = 'Jinzhu' ORDER BY id LIMIT 1;
// user -> User{ID: 111, Name: "Jinzhu", Age: 18} if found
为属性使用 Assign
Assign
方法允许您在结构上设置属性,不管是否找到记录。 这些属性设定在结构上,但不用于生成 SQL 查询,最终数据不会被保存到数据库。
// 根据所给条件和分配的属性初始化,不管记录是否存在
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user)
// user -> User{Name: "non_existing", Age: 20} if not found
// 如果找到了名为“Jinzhu”的用户,使用分配的属性更新结构体
db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 20}).FirstOrInit(&user)
// SQL: SELECT * FROM USERS WHERE name = 'Jinzhu' ORDER BY id LIMIT 1;
// user -> User{ID: 111, Name: "Jinzhu", Age: 20} if found
Assign
方法的主要作用是在应用程序层面上临时修改模型的属性,而不是持久化这些更改。这在处理复杂的业务逻辑时非常有用,因为它允许你在不更改数据库状态的情况下,根据需要调整模型的状态。此外,它还可以用于在创建新记录或更新现有记录之前,设置默认值或预设值。虽然
Assign
方法不能持久化更改这些使用的数据,但可以间接性更改,上面例子里面被初始化后的结构体数据都存入了&user
中,意味着我们如果要持久化更改这些在数据库对应的数据,就可以写多一条GORM操作语句进行数据操作。例如:// 添加数据进数据库 // 假设没有找到记录,那么 user 将被初始化 db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user) // 随后可以创建新的记录 db.Create(&user)
// 更新现有数据库对应数据 // 假设找到了记录,并且 Age 被设置为 20 db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 20}).FirstOrInit(&user) // 可以对 user 进行更多修改 user.Email = "jinzhu@example.com" // 保存更改到数据库 db.Save(&user)
// 条件性更新 db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 25}).FirstOrInit(&user) // 检查模型的某个属性,决定是否更新 if user.Age != 25 { user.Age = 25 db.Save(&user) // 只有当 Age 发生变化时才保存 }
做上述这些操作的时候要注意一些小细节:
- 事务性:确保您的操作具有事务性,特别是在进行创建或更新操作时。
- 并发问题:在并发环境中,需要注意其他可能同时修改相同记录的情况。
- 数据验证:在保存模型到数据库之前,确保进行适当的数据验证和清理。
FirstOrInit
, 以及 Attrs
和 Assign
, 提供了一种强大和灵活的方法来确保记录的存在,并且在一个步骤中以特定的属性初始化或更新。
FirstOrCreate
FirstOrCreate
用于获取(查询)与特定条件匹配的第一条记录,或者如果没有找到匹配的记录,创建一个新的记录。 这个方法在结构和map条件下都是有效的。 受 RowsAffected
影响的属性有助于确定创建或更新记录的数量。
原话:FirstOrCreate finds the first matching record, otherwise if not found creates a new instance with given conds.
// 如果没找到,就创建一个新纪录
result := db.FirstOrCreate(&user, User{Name: "non_existing"})
// SQL: INSERT INTO "users" (name) VALUES ("non_existing");
// user -> User{ID: 112, Name: "non_existing"}
// result.RowsAffected // => 1 (record created)
// 如果用户已经被找到,不会创建新纪录
result = db.Where(User{Name: "jinzhu"}).FirstOrCreate(&user)
// user -> User{ID: 111, Name: "jinzhu", Age: 18}
// result.RowsAffected // => 0 (no record created)
配合 Attrs
使用 FirstOrCreate
Attrs
可以用于指定新记录的附加属性。 这些属性用于创建,但不在初始搜索查询中。
// 如果没找到,根据额外属性创建新的记录
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
// SQL: SELECT * FROM users WHERE name = 'non_existing';
// SQL: INSERT INTO "users" (name, age) VALUES ("non_existing", 20);
// user -> User{ID: 112, Name: "non_existing", Age: 20}
// 如果user被找到了,`Attrs` 会被忽略
db.Where(User{Name: "jinzhu"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
// SQL: SELECT * FROM users WHERE name = 'jinzhu';
// user -> User{ID: 111, Name: "jinzhu", Age: 18}
配合 Assign
使用 FirstOrCreate
不管记录是否被找到,Assign
方法都会设置记录中的属性。 并且这些属性被保存到数据库。
// 如果没找到记录,通过 `Assign` 属性 初始化并且保存新的记录
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrCreate(&user)
// SQL: SELECT * FROM users WHERE name = 'non_existing';
// SQL: INSERT INTO "users" (name, age) VALUES ("non_existing", 20);
// user -> User{ID: 112, Name: "non_existing", Age: 20}
// 通过 `Assign` 属性 更新记录
db.Where(User{Name: "jinzhu"}).Assign(User{Age: 20}).FirstOrCreate(&user)
// SQL: SELECT * FROM users WHERE name = 'jinzhu';
// SQL: UPDATE users SET age=20 WHERE id = 111;
// user -> User{ID: 111, Name: "Jinzhu", Age: 20}
评论(0)