golang gorm的预加载及软删硬删的数据操作示例
来源:脚本之家
时间:2023-01-22 10:25:23 380浏览 收藏
IT行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰。所以我们需要踏踏实实的不断学习,精进自己的技术,尤其是初学者。今天golang学习网给大家整理了《golang gorm的预加载及软删硬删的数据操作示例》,聊聊gorm、预加载、软删硬删,我们一起来看看吧!
1. orm读写数据
1. 创建
1.1. 创建记录
1 2 3 4 | user := User{Name: "Jinzhu" , Age: 18 , Birthday: time.Now()} db.NewRecord(user) // => 主键为空返回`true` db.Create(&user) db.NewRecord(user) // => 创建`user`后返回`false` |
1.2. 默认值
您可以在gorm tag中定义默认值,然后插入SQL将忽略具有默认值的这些字段,并且其值为空,并且在将记录插入数据库后,gorm将从数据库加载这些字段的值。
1 2 3 4 5 6 7 8 9 10 | type Animal struct { ID int64 Name string `gorm: "default:'galeone'" ` Age int64 } var animal = Animal{Age: 99 , Name: "" } db.Create(&animal) // INSERT INTO animals("age") values('99'); // SELECT name from animals WHERE ID=111; // 返回主键为 111 // animal.Name => 'galeone' |
1.3. 在Callbacks中设置主键
如果要在BeforeCreate回调中设置主字段的值,可以使用scope.SetColumn,例如:
1 2 3 4 | func (user *User) BeforeCreate(scope *gorm.Scope) error { scope.SetColumn( "ID" , uuid. New ()) return nil } |
1.4. 扩展创建选项
1 2 3 | // 为Instert语句添加扩展SQL选项 db.Set( "gorm:insert_option" , "ON CONFLICT" ).Create(&product) // INSERT INTO products (name, code) VALUES ("name", "code") ON CONFLICT; |
2. 查询
1 2 3 4 5 6 7 8 9 10 11 12 | // 获取第一条记录,按主键排序 db.First(&user) //// SELECT * FROM users ORDER BY id LIMIT 1; // 获取最后一条记录,按主键排序 db.Last(&user) //// SELECT * FROM users ORDER BY id DESC LIMIT 1; // 获取所有记录 db.Find(&users) //// SELECT * FROM users; // 使用主键获取记录 db.First(&user, 10 ) //// SELECT * FROM users WHERE id = 10; |
2.1. Where查询条件 (简单SQL)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // 获取第一个匹配记录 db.Where( "name = ?" , "jinzhu" ).First(&user) //// SELECT * FROM users WHERE name = 'jinzhu' limit 1; // 获取所有匹配记录 db.Where( "name = ?" , "jinzhu" ).Find(&users) //// SELECT * FROM users WHERE name = 'jinzhu'; db.Where( "name ?" , "jinzhu" ).Find(&users) // IN db.Where( "name in (?)" , [] string { "jinzhu" , "jinzhu 2" }).Find(&users) // LIKE db.Where( "name LIKE ?" , "%jin%" ).Find(&users) // AND db.Where( "name = ? AND age >= ?" , "jinzhu" , "22" ).Find(&users) // Time db.Where( "updated_at > ?" , lastWeek).Find(&users) db.Where( "created_at BETWEEN ? AND ?" , lastWeek, today).Find(&users) |
2.2. Where查询条件 (Struct & Map)
注意:当使用struct查询时,GORM将只查询那些具有值的字段
1 2 3 4 5 6 7 8 9 | // Struct db.Where(&User{Name: "jinzhu" , Age: 20 }).First(&user) //// SELECT * FROM users WHERE name = "jinzhu" AND age = 20 LIMIT 1; // Map db.Where( map [ string ] interface {}{ "name" : "jinzhu" , "age" : 20 }).Find(&users) //// SELECT * FROM users WHERE name = "jinzhu" AND age = 20; // 主键的Slice db.Where([] int64 { 20 , 21 , 22 }).Find(&users) //// SELECT * FROM users WHERE id IN (20, 21, 22); |
2.3. Not条件查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | db.Not( "name" , "jinzhu" ).First(&user) //// SELECT * FROM users WHERE name "jinzhu" LIMIT 1; // Not In db.Not( "name" , [] string { "jinzhu" , "jinzhu 2" }).Find(&users) //// SELECT * FROM users WHERE name NOT IN ("jinzhu", "jinzhu 2"); // Not In slice of primary keys db.Not([] int64 { 1 , 2 , 3 }).First(&user) //// SELECT * FROM users WHERE id NOT IN (1,2,3); db.Not([] int64 {}).First(&user) //// SELECT * FROM users; // Plain SQL db.Not( "name = ?" , "jinzhu" ).First(&user) //// SELECT * FROM users WHERE NOT(name = "jinzhu"); // Struct db.Not(User{Name: "jinzhu" }).First(&user) //// SELECT * FROM users WHERE name "jinzhu"; |
2.4. 带内联条件的查询
注意:使用主键查询时,应仔细检查所传递的值是否为有效主键,以避免SQL注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // 按主键获取 db.First(&user, 23 ) //// SELECT * FROM users WHERE id = 23 LIMIT 1; // 简单SQL db.Find(&user, "name = ?" , "jinzhu" ) //// SELECT * FROM users WHERE name = "jinzhu"; db.Find(&users, "name ? AND age > ?" , "jinzhu" , 20 ) //// SELECT * FROM users WHERE name "jinzhu" AND age > 20; // Struct db.Find(&users, User{Age: 20 }) //// SELECT * FROM users WHERE age = 20; // Map db.Find(&users, map [ string ] interface {}{ "age" : 20 }) //// SELECT * FROM users WHERE age = 20; |
2.5. Or条件查询
1 2 3 4 5 6 7 | db.Where( "role = ?" , "admin" ).Or( "role = ?" , "super_admin" ).Find(&users) //// SELECT * FROM users WHERE role = 'admin' OR role = 'super_admin'; // Struct db.Where( "name = 'jinzhu'" ).Or(User{Name: "jinzhu 2" }).Find(&users) //// SELECT * FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'; // Map db.Where( "name = 'jinzhu'" ).Or( map [ string ] interface {}{ "name" : "jinzhu 2" }).Find(&users) |
2.6. 查询链
Gorm有一个可链接的API,你可以这样使用它
1 2 3 | db.Where( "name ?" , "jinzhu" ).Where( "age >= ? and role ?" , 20 , "admin" ).Find(&users) //// SELECT * FROM users WHERE name 'jinzhu' AND age >= 20 AND role 'admin'; db.Where( "role = ?" , "admin" ).Or( "role = ?" , "super_admin" ).Not( "name = ?" , "jinzhu" ).Find(&users) |
2.7. 扩展查询选项
1 2 3 | // 为Select语句添加扩展SQL选项 db.Set( "gorm:query_option" , "FOR UPDATE" ).First(&user, 10 ) //// SELECT * FROM users WHERE id = 10 FOR UPDATE; |
2.8. FirstOrInit
获取第一个匹配的记录,或者使用给定的条件初始化一个新的记录(仅适用于struct,map条件)
1 2 3 4 5 6 7 8 | // Unfound db.FirstOrInit(&user, User{Name: "non_existing" }) //// user -> User{Name: "non_existing"} // Found db.Where(User{Name: "Jinzhu" }).FirstOrInit(&user) //// user -> User{Id: 111, Name: "Jinzhu", Age: 20} db.FirstOrInit(&user, map [ string ] interface {}{ "name" : "jinzhu" }) //// user -> User{Id: 111, Name: "Jinzhu", Age: 20} |
2.9. Attrs
如果未找到记录,则使用参数初始化结构
1 2 3 4 5 6 7 8 9 10 11 | // Unfound db.Where(User{Name: "non_existing" }).Attrs(User{Age: 20 }).FirstOrInit(&user) //// SELECT * FROM USERS WHERE name = 'non_existing'; //// user -> User{Name: "non_existing", Age: 20} db.Where(User{Name: "non_existing" }).Attrs( "age" , 20 ).FirstOrInit(&user) //// SELECT * FROM USERS WHERE name = 'non_existing'; //// user -> User{Name: "non_existing", Age: 20} // Found db.Where(User{Name: "Jinzhu" }).Attrs(User{Age: 30 }).FirstOrInit(&user) //// SELECT * FROM USERS WHERE name = jinzhu'; //// user -> User{Id: 111, Name: "Jinzhu", Age: 20} |
2.10. Assign
将参数分配给结果,不管它是否被找到
1 2 3 4 5 6 7 | // Unfound db.Where(User{Name: "non_existing" }).Assign(User{Age: 20 }).FirstOrInit(&user) //// user -> User{Name: "non_existing", Age: 20} // Found db.Where(User{Name: "Jinzhu" }).Assign(User{Age: 30 }).FirstOrInit(&user) //// SELECT * FROM USERS WHERE name = jinzhu'; //// user -> User{Id: 111, Name: "Jinzhu", Age: 30} |
2.11. FirstOrCreate
获取第一个匹配的记录,或创建一个具有给定条件的新记录(仅适用于struct, map条件)
1 2 3 4 5 6 7 | // Unfound db.FirstOrCreate(&user, User{Name: "non_existing" }) //// INSERT INTO "users" (name) VALUES ("non_existing"); //// user -> User{Id: 112, Name: "non_existing"} // Found db.Where(User{Name: "Jinzhu" }).FirstOrCreate(&user) //// user -> User{Id: 111, Name: "Jinzhu"} |
2.12. Attrs
如果未找到记录,则为参数分配结构
1 2 3 4 5 6 7 8 9 | // Unfound db.Where(User{Name: "non_existing" }).Attrs(User{Age: 20 }).FirstOrCreate(&user) //// SELECT * FROM users WHERE name = 'non_existing'; //// INSERT INTO "users" (name, age) VALUES ("non_existing", 20); //// user -> User{Id: 112, Name: "non_existing", Age: 20} // Found db.Where(User{Name: "jinzhu" }).Attrs(User{Age: 30 }).FirstOrCreate(&user) //// SELECT * FROM users WHERE name = 'jinzhu'; //// user -> User{Id: 111, Name: "jinzhu", Age: 20} |
2.13. Assign
将其分配给记录,而不管它是否被找到,并保存回数据库。
1 2 3 4 5 6 7 8 9 10 | // Unfound db.Where(User{Name: "non_existing" }).Assign(User{Age: 20 }).FirstOrCreate(&user) //// SELECT * FROM users WHERE name = 'non_existing'; //// INSERT INTO "users" (name, age) VALUES ("non_existing", 20); //// user -> User{Id: 112, Name: "non_existing", Age: 20} // Found db.Where(User{Name: "jinzhu" }).Assign(User{Age: 30 }).FirstOrCreate(&user) //// SELECT * FROM users WHERE name = 'jinzhu'; //// UPDATE users SET age=30 WHERE id = 111; //// user -> User{Id: 111, Name: "jinzhu", Age: 30} |
2.14. Select
指定要从数据库检索的字段,默认情况下,将选择所有字段;
1 2 3 4 5 6 | db. Select ( "name, age" ).Find(&users) //// SELECT name, age FROM users; db. Select ([] string { "name" , "age" }).Find(&users) //// SELECT name, age FROM users; db.Table( "users" ). Select ( "COALESCE(age,?)" , 42 ).Rows() //// SELECT COALESCE(age,'42') FROM users; |
2.15. Order
在从数据库检索记录时指定顺序,将重排序设置为true
以覆盖定义的条件
1 2 3 4 5 6 7 8 9 | db.Order( "age desc, name" ).Find(&users) //// SELECT * FROM users ORDER BY age desc, name; // Multiple orders db.Order( "age desc" ).Order( "name" ).Find(&users) //// SELECT * FROM users ORDER BY age desc, name; // ReOrder db.Order( "age desc" ).Find(&users1).Order( "age" , true ).Find(&users2) //// SELECT * FROM users ORDER BY age desc; (users1) //// SELECT * FROM users ORDER BY age; (users2) |
2.16. Limit
指定要检索的记录数
1 2 3 4 5 6 | db.Limit( 3 ).Find(&users) //// SELECT * FROM users LIMIT 3; // Cancel limit condition with -1 db.Limit( 10 ).Find(&users1).Limit(- 1 ).Find(&users2) //// SELECT * FROM users LIMIT 10; (users1) //// SELECT * FROM users; (users2) |
2.17. Offset
指定在开始返回记录之前要跳过的记录数
1 2 3 4 5 6 | db.Offset( 3 ).Find(&users) //// SELECT * FROM users OFFSET 3; // Cancel offset condition with -1 db.Offset( 10 ).Find(&users1).Offset(- 1 ).Find(&users2) //// SELECT * FROM users OFFSET 10; (users1) //// SELECT * FROM users; (users2) |
eg:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | type Info struct { Id int `json: "id" ` Code string `json: "code" ` HwCode string `json: "hw_code" ` Name string `json: "name" ` Des string `json: "des" ` Created int64 `json: "created" ` Updated int64 `json: "updated" ` BrandId int `json: "brand_id" ` } func (Info) TableName() string { return "bike_color" } func (o object) QueryInfo2(id int ) *Info { r := new (Info) o.gDb.Where( "id = ?" ,id).Find(&r) return r } // 列表 func (o object) QueryList2(page, PageSize int ) (list []Info, total int ) { o.gDb.Offset((page- 1 )*PageSize).Limit(PageSize).Find(&list) total = len (list) return } |
2.18. Count
获取模型的记录数
1 2 3 4 5 6 7 | db.Where( "name = ?" , "jinzhu" ).Or( "name = ?" , "jinzhu 2" ).Find(&users).Count(&count) //// SELECT * from USERS WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (users) //// SELECT count(*) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (count) db.Model(&User{}).Where( "name = ?" , "jinzhu" ).Count(&count) //// SELECT count(*) FROM users WHERE name = 'jinzhu'; (count) db.Table( "deleted_users" ).Count(&count) //// SELECT count(*) FROM deleted_users; |
2.19. Group & Having
1 2 3 4 5 6 7 8 9 10 11 12 13 | rows, err := db.Table( "orders" ). Select ( "date(created_at) as date, sum(amount) as total" ).Group( "date(created_at)" ).Rows() for rows.Next() { ... } rows, err := db.Table( "orders" ). Select ( "date(created_at) as date, sum(amount) as total" ).Group( "date(created_at)" ).Having( "sum(amount) > ?" , 100 ).Rows() for rows.Next() { ... } type Result struct { Date time.Time Total int64 } db.Table( "orders" ). Select ( "date(created_at) as date, sum(amount) as total" ).Group( "date(created_at)" ).Having( "sum(amount) > ?" , 100 ).Scan(&results) |
2.20. Join
指定连接条件
1 2 3 4 5 6 7 | rows, err := db.Table( "users" ). Select ( "users.name, emails.email" ).Joins( "left join emails on emails.user_id = users.id" ).Rows() for rows.Next() { ... } db.Table( "users" ). Select ( "users.name, emails.email" ).Joins( "left join emails on emails.user_id = users.id" ).Scan(&results) // 多个连接与参数 db.Joins( "JOIN emails ON emails.user_id = users.id AND emails.email = ?" , "jinzhu@example.org" ).Joins( "JOIN credit_cards ON credit_cards.user_id = users.id" ).Where( "credit_cards.number = ?" , "411111111111" ).Find(&user) |
2.21. Pluck
将模型中的单个列作为地图查询,如果要查询多个列,可以使用Scan
1 2 3 4 5 6 7 | var ages [] int64 db.Find(&users).Pluck( "age" , &ages) var names [] string db.Model(&User{}).Pluck( "name" , &names) db.Table( "deleted_users" ).Pluck( "name" , &names) // 要返回多个列,做这样: db. Select ( "name, age" ).Find(&users) |
2.22. Scan
将结果扫描到另一个结构中。
1 2 3 4 5 6 7 8 | type Result struct { Name string Age int } var result Result db.Table( "users" ). Select ( "name, age" ).Where( "name = ?" , 3 ).Scan(&result) // Raw SQL db.Raw( "SELECT name, age FROM users WHERE name = ?" , 3 ).Scan(&result) |
2.23. Scopes
将当前数据库连接传递到func(*DB) *DB
,可以用于动态添加条件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | func AmountGreaterThan1000(db *gorm.DB) *gorm.DB { return db.Where( "amount > ?" , 1000 ) } func PaidWithCreditCard(db *gorm.DB) *gorm.DB { return db.Where( "pay_mode_sign = ?" , "C" ) } func PaidWithCod(db *gorm.DB) *gorm.DB { return db.Where( "pay_mode_sign = ?" , "C" ) } func OrderStatus(status [] string ) func (db *gorm.DB) *gorm.DB { return func (db *gorm.DB) *gorm.DB { return db.Scopes(AmountGreaterThan1000).Where( "status in (?)" , status) } } db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders) // 查找所有信用卡订单和金额大于1000 db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders) // 查找所有COD订单和金额大于1000 db.Scopes(OrderStatus([] string { "paid" , "shipped" })).Find(&orders) // 查找所有付费,发货订单 |
2.24. 指定表名
1 2 3 4 5 6 7 | // 使用User结构定义创建`deleted_users`表 db.Table( "deleted_users" ).CreateTable(&User{}) var deleted_users []User db.Table( "deleted_users" ).Find(&deleted_users) //// SELECT * FROM deleted_users; db.Table( "deleted_users" ).Where( "name = ?" , "jinzhu" ). Delete () //// DELETE FROM deleted_users WHERE name = 'jinzhu'; |
3. 预加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | db.Preload( "Orders" ).Find(&users) //// SELECT * FROM users; //// SELECT * FROM orders WHERE user_id IN (1,2,3,4); db.Preload( "Orders" , "state NOT IN (?)" , "cancelled" ).Find(&users) //// SELECT * FROM users; //// SELECT * FROM orders WHERE user_id IN (1,2,3,4) AND state NOT IN ('cancelled'); db.Where( "state = ?" , "active" ).Preload( "Orders" , "state NOT IN (?)" , "cancelled" ).Find(&users) //// SELECT * FROM users WHERE state = 'active'; //// SELECT * FROM orders WHERE user_id IN (1,2) AND state NOT IN ('cancelled'); db.Preload( "Orders" ).Preload( "Profile" ).Preload( "Role" ).Find(&users) //// SELECT * FROM users; //// SELECT * FROM orders WHERE user_id IN (1,2,3,4); // has many //// SELECT * FROM profiles WHERE user_id IN (1,2,3,4); // has one //// SELECT * FROM roles WHERE id IN (4,5,6); // belongs to |
3.1. 自定义预加载SQL
您可以通过传递func(db *gorm.DB) *gorm.DB
(与Scopes的使用方法相同)来自定义预加载SQL,例如:
1 2 3 4 5 | db.Preload( "Orders" , func (db *gorm.DB) *gorm.DB { return db.Order( "orders.amount DESC" ) }).Find(&users) //// SELECT * FROM users; //// SELECT * FROM orders WHERE user_id IN (1,2,3,4) order by orders.amount DESC; |
3.2. 嵌套预加载
1 2 | db.Preload( "Orders.OrderItems" ).Find(&users) db.Preload( "Orders" , "state = ?" , "paid" ).Preload( "Orders.OrderItems" ).Find(&users) |
4. 更新
4.1. 更新全部字段
Save
将包括执行更新SQL时的所有字段,即使它没有更改
1 2 3 4 5 | db.First(&user) user.Name = "jinzhu 2" user.Age = 100 db.Save(&user) //// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111; |
4.2. 更新更改字段
如果只想更新更改的字段,可以使用Update
, Updates
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // 更新单个属性(如果更改) db.Model(&user).Update( "name" , "hello" ) //// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111; // 使用组合条件更新单个属性 db.Model(&user).Where( "active = ?" , true ).Update( "name" , "hello" ) //// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true; // 使用`map`更新多个属性,只会更新这些更改的字段 db.Model(&user).Updates( map [ string ] interface {}{ "name" : "hello" , "age" : 18 , "actived" : false }) //// UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111; // 使用`struct`更新多个属性,只会更新这些更改的和非空白字段 db.Model(&user).Updates(User{Name: "hello" , Age: 18 }) //// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111; // 警告:当使用struct更新时,FORM将仅更新具有非空值的字段 // 对于下面的更新,什么都不会更新为"",0,false是其类型的空白值 db.Model(&user).Updates(User{Name: "" , Age: 0 , Actived: false }) |
4.3. 更新选择的字段
如果您只想在更新时更新或忽略某些字段,可以使用Select
, Omit
1 2 3 4 | db.Model(&user). Select ( "name" ).Updates( map [ string ] interface {}{ "name" : "hello" , "age" : 18 , "actived" : false }) //// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111; db.Model(&user).Omit( "name" ).Updates( map [ string ] interface {}{ "name" : "hello" , "age" : 18 , "actived" : false }) //// UPDATE users SET age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111; |
4.4. 更新更改字段但不进行Callbacks
以上更新操作将执行模型的BeforeUpdate
, AfterUpdate
方法,更新其UpdatedAt
时间戳,在更新时保存它的Associations
,如果不想调用它们,可以使用UpdateColumn
, UpdateColumns
1 2 3 4 5 6 | // 更新单个属性,类似于`Update` db.Model(&user).UpdateColumn( "name" , "hello" ) //// UPDATE users SET name='hello' WHERE id = 111; // 更新多个属性,与“更新”类似 db.Model(&user).UpdateColumns(User{Name: "hello" , Age: 18 }) //// UPDATE users SET name='hello', age=18 WHERE id = 111; |
4.5. Batch Updates 批量更新
Callbacks
在批量更新时不会运行
1 2 3 4 5 6 7 | db.Table( "users" ).Where( "id IN (?)" , [] int { 10 , 11 }).Updates( map [ string ] interface {}{ "name" : "hello" , "age" : 18 }) //// UPDATE users SET name='hello', age=18 WHERE id IN (10, 11); // 使用struct更新仅适用于非零值,或使用map[string]interface{} db.Model(User{}).Updates(User{Name: "hello" , Age: 18 }) //// UPDATE users SET name='hello', age=18; // 使用`RowsAffected`获取更新记录计数 db.Model(User{}).Updates(User{Name: "hello" , Age: 18 }).RowsAffected |
4.6. 使用SQL表达式更新
1 2 3 4 5 6 7 8 | DB.Model(&product).Update( "price" , gorm.Expr( "price * ? + ?" , 2 , 100 )) //// UPDATE "products" SET "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2'; DB.Model(&product).Updates( map [ string ] interface {}{ "price" : gorm.Expr( "price * ? + ?" , 2 , 100 )}) //// UPDATE "products" SET "price" = price * '2' + '100', "updated_at" = '2013-11-17 21:34:10' WHERE "id" = '2'; DB.Model(&product).UpdateColumn( "quantity" , gorm.Expr( "quantity - ?" , 1 )) //// UPDATE "products" SET "quantity" = quantity - 1 WHERE "id" = '2'; DB.Model(&product).Where( "quantity > 1" ).UpdateColumn( "quantity" , gorm.Expr( "quantity - ?" , 1 )) //// UPDATE "products" SET "quantity" = quantity - 1 WHERE "id" = '2' AND quantity > 1; |
4.7. 在Callbacks中更改更新值
如果要使用BeforeUpdate
, BeforeSave
更改回调中的更新值,可以使用scope.SetColumn
,例如
1 2 3 4 5 | func (user *User) BeforeSave(scope *gorm.Scope) (err error ) { if pw, err := bcrypt.GenerateFromPassword(user.Password, 0 ); err == nil { scope.SetColumn( "EncryptedPassword" , pw) } } |
4.8. 额外更新选项
1 2 3 | // 为Update语句添加额外的SQL选项 db.Model(&user).Set( "gorm:update_option" , "OPTION (OPTIMIZE FOR UNKNOWN)" ).Update( "name, " hello") //// UPDATE users SET name='hello', updated_at = '2013-11-17 21:34:10' WHERE id=111 OPTION (OPTIMIZE FOR UNKNOWN); |
5. 删除/软删除
警告 删除记录时,需要确保其主要字段具有值,GORM将使用主键删除记录,如果主要字段为空,GORM将删除模型的所有记录
1 2 3 4 5 6 | // 删除存在的记录 db. Delete (&email) //// DELETE from emails where id=10; // 为Delete语句添加额外的SQL选项 db.Set( "gorm:delete_option" , "OPTION (OPTIMIZE FOR UNKNOWN)" ). Delete (&email) //// DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN); |
5.1. 批量删除
删除所有匹配记录
1 2 3 4 | db.Where( "email LIKE ?" , "%jinzhu%" ). Delete (Email{}) //// DELETE from emails where email LIKE "%jinhu%"; db. Delete (Email{}, "email LIKE ?" , "%jinzhu%" ) //// DELETE from emails where email LIKE "%jinhu%"; |
5.2. 软删除
如果模型有DeletedAt
字段,它将自动获得软删除功能! 那么在调用Delete
时不会从数据库中永久删除,而是只将字段DeletedAt
的值设置为当前时间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | db. Delete (&user) //// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111; // 批量删除 db.Where( "age = ?" , 20 ). Delete (&User{}) //// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20; // 软删除的记录将在查询时被忽略 db.Where( "age = 20" ).Find(&user) //// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL; // 使用Unscoped查找软删除的记录 db.Unscoped().Where( "age = 20" ).Find(&users) //// SELECT * FROM users WHERE age = 20; // 使用Unscoped永久删除记录 db.Unscoped(). Delete (&order) //// DELETE FROM orders WHERE id=10; |
6. 关联
默认情况下,当创建/更新记录时,GORM将保存其关联,如果关联具有主键,GORM将调用Update来保存它,否则将被创建。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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@example.com" }, }, Languages: []Language{ {Name: "ZH" }, {Name: "EN" }, }, } db.Create(&user) //// BEGIN TRANSACTION; //// INSERT INTO "addresses" (address1) VALUES ("Billing Address - Address 1"); //// INSERT INTO "addresses" (address1) VALUES ("Shipping Address - Address 1"); //// 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"); //// INSERT INTO "emails" (user_id,email) VALUES (111, "jinzhu-2@example.com"); //// INSERT INTO "languages" ("name") VALUES ('ZH'); //// INSERT INTO user_languages ("user_id","language_id") VALUES (111, 1); //// INSERT INTO "languages" ("name") VALUES ('EN'); //// INSERT INTO user_languages ("user_id","language_id") VALUES (111, 2); //// COMMIT; db.Save(&user) |
6.1. 创建/更新时跳过保存关联
默认情况下保存记录时,GORM也会保存它的关联,你可以通过设置gorm:save_associations
为false
跳过它。
1 2 | db.Set( "gorm:save_associations" , false ).Create(&user) db.Set( "gorm:save_associations" , false ).Save(&user) |
6.2. tag设置跳过保存关联
您可以使用tag来配置您的struct,以便在创建/更新时不会保存关联
1 2 3 4 5 6 7 8 9 10 | type User struct { gorm.Model Name string CompanyID uint Company Company `gorm: "save_associations:false" ` } type Company struct { gorm.Model Name string } |
终于介绍完啦!小伙伴们,这篇关于《golang gorm的预加载及软删硬删的数据操作示例》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布Golang相关知识,快来关注吧!
-
241 收藏
-
134 收藏
-
184 收藏
-
187 收藏
-
197 收藏
-
244 收藏
-
152 收藏
-
225 收藏
-
348 收藏
-
371 收藏
-
232 收藏
-
442 收藏
-
198 收藏
-
307 收藏
-
386 收藏
-
414 收藏
-
468 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习
-
- 心灵美的金针菇
- 受益颇多,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢大佬分享技术文章!
- 2023-05-14 10:50:12
-
- 悦耳的小猫咪
- 太详细了,码住,感谢博主的这篇技术贴,我会继续支持!
- 2023-04-23 17:27:43
-
- 沉默的老鼠
- 很详细,已加入收藏夹了,感谢up主的这篇技术文章,我会继续支持!
- 2023-02-22 10:16:58
-
- 生动的红酒
- 太给力了,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢博主分享文章内容!
- 2023-02-08 07:54:14
-
- 热情的跳跳糖
- 这篇技术贴太及时了,很详细,很好,码住,关注作者大大了!希望作者大大能多写Golang相关的文章。
- 2023-02-06 06:15:45
-
- 高兴的魔镜
- 这篇技术贴太及时了,大佬加油!
- 2023-01-30 05:41:55
-
- 善良的台灯
- 这篇文章出现的刚刚好,太细致了,很棒,已收藏,关注作者了!希望作者能多写Golang相关的文章。
- 2023-01-29 10:47:45
-
- 重要的楼房
- 这篇技术文章真及时,好细啊,很有用,码起来,关注up主了!希望up主能多写Golang相关的文章。
- 2023-01-28 14:34:21