简单电商网站模板下载,网站开发多少工资,wordpress教程之,茂名住房和城乡建设厅网站1、傻瓜示例 GORM通过将数据库表中的数据映射到面向对象的模型中#xff0c;简化了数据库操作#xff0c;使得开发者可以很方便的使用代码来操作数据库#xff0c;而无需编写SQL语句。
目前有个mysql表#xff1a;miniprogram_orders#xff0c;其存储了所有用户对应的订…1、傻瓜示例 GORM通过将数据库表中的数据映射到面向对象的模型中简化了数据库操作使得开发者可以很方便的使用代码来操作数据库而无需编写SQL语句。
目前有个mysql表miniprogram_orders其存储了所有用户对应的订单表结构如下 建表sql语句
CREATE TABLE miniprogram_orders (id bigint NOT NULL AUTO_INCREMENT,order_sn varchar(255) NOT NULL DEFAULT COMMENT 订单号,uid varchar(50) NOT NULL DEFAULT COMMENT 用户唯一标识,name varchar(255) NOT NULL DEFAULT COMMENT 姓名,sex varchar(5) NOT NULL DEFAULT COMMENT 性别,identify_card_number varchar(20) NOT NULL DEFAULT COMMENT 身份证号,country varchar(15) NOT NULL DEFAULT 0 COMMENT 国家,identify_card_type varchar(20) NOT NULL DEFAULT COMMENT 证件类型,born_date varchar(11) NOT NULL DEFAULT COMMENT 出生日期,nation varchar(10) NOT NULL DEFAULT COMMENT 民族,phone_num varchar(20) NOT NULL DEFAULT COMMENT 手机号,email varchar(255) NOT NULL DEFAULT COMMENT 邮箱,address varchar(255) NOT NULL DEFAULT COMMENT 现居地址,commodity_id varchar(255) NOT NULL DEFAULT COMMENT 商品id,play_type varchar(255) NOT NULL DEFAULT COMMENT 比赛类型:团体赛、个人赛,application_pay float NOT NULL DEFAULT 0 COMMENT 报名费用,status int NOT NULL DEFAULT 0 COMMENT 订单状态,created_at timestamp NULL DEFAULT CURRENT_TIMESTAMP,updated_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,deleted_at timestamp NULL DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (id),KEY uid (uid),KEY order_sn (order_sn)
) ENGINEInnoDB AUTO_INCREMENT2 DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci
表中有一条记录如下
mysql select * from miniprogram_orders \G;
*************************** 1. row ***************************id: 1order_sn: c9dbe95f51d1391622eebc08a7afa671uid: liupeng20240908name: 棉花糖sex: 男
identify_card_number: 130627202410031234country: 中国identify_card_type: 身份证born_date: 2024-10-03nation: 汉phone_num: 13988886666email: mianhuatang163.comaddress: 北京天安门commodity_id: cc800badc8b91d51a40c092feb31848fplay_type: 个人赛application_pay: 99status: 1created_at: 2024-09-08 21:53:19updated_at: 2024-09-17 18:12:05deleted_at: NULL
1 row in set (0.00 sec)ERROR:
No query specified
假如有一个需求查找某个人所有订单代码实现如下
定义表对应结构体
type MiniprogramOrder struct {gorm.Model //gorm预定义结构体Uid string json:uidOrderSn string json:order_snName string json:nameSex string json:sexIdentifyCardNumber string json:identify_card_numberCountry string json:countryIdentifyCardType string json:identify_card_typeBornDate string json:born_dateNation string json:nationPhoneNum string json:phone_numberEmail string json:emailAddress string json:addressCommodityId string json:commodity_idPlayType string json:play_typeApplicationPay float32 json:application_payStatus int json:status
}
gorm.Model为gorm预定义的结构体其定义如下
type Model struct {ID uint gorm:primarykeyCreatedAt time.TimeUpdatedAt time.TimeDeletedAt DeletedAt gorm:index
}
ID 每个记录的唯一标识符主键。CreatedAt 在创建记录时自动设置为当前时间。UpdatedAt每当记录更新时自动更新为当前时间。DeletedAt用于软删除将记录标记为已删除而实际上并未从数据库中删除。 上面为数据库表信息以及对应结构体定义下面是代码实现部分
创建数据库链接:
func initMysql() *gorm.DB {var err errordsn : user:passwordtcp(127.0.0.1:3306)/dbname?charsetutf8mb4parseTimeTruelocLocalclient, err : gorm.Open(mysql.Open(dsn), gorm.Config{})if err ! nil {fmt.Println(failed to connect database err.Error())return nil}fmt.Println(db connect success!)return client
}
查找数据库记录
// 根据uid查询订单
func Select(db *gorm.DB, uid string) []MiniprogramOrder {orderList : []MiniprogramOrder{}db.Where(uid ?, uid).Find(orderList)return orderList
} 测试代码
func main() {var json jsoniter.ConfigCompatibleWithStandardLibrarydb : initMysql()if db nil {return}orderList : Select(db, liupeng20240908)str, _ : json.MarshalToString(orderList)fmt.Println(str)
}
代码打印
[{ID: 1,CreatedAt: 2024-09-08T21:53:1908:00,UpdatedAt: 2024-09-17T18:12:0508:00,DeletedAt: null,uid: liupeng20240908,order_sn: c9dbe95f51d1391622eebc08a7afa671,name: 棉花糖,sex: 男,identify_card_number: 130627202410031234,country: 中国,identify_card_type: 身份证,born_date: 2024-10-03,nation: 汉,phone_number: 13988886666,email: mianhuatang163.com,address: 北京天安门,commodity_id: cc800badc8b91d51a40c092feb31848f,play_type: 个人赛,application_pay: 99,status: 1}
]
全部代码如下
package mainimport (fmtjsoniter github.com/json-iterator/gogorm.io/driver/mysqlgorm.io/gorm
)type MiniprogramOrder struct {gorm.Model //gorm预定义结构体Uid string json:uidOrderSn string json:order_snName string json:nameSex string json:sexIdentifyCardNumber string json:identify_card_numberCountry string json:countryIdentifyCardType string json:identify_card_typeBornDate string json:born_dateNation string json:nationPhoneNum string json:phone_numberEmail string json:emailAddress string json:addressCommodityId string json:commodity_idPlayType string json:play_typeApplicationPay float32 json:application_payStatus int json:status
}func initMysql() *gorm.DB {var err errordsn : user:passwordtcp(127.0.0.1:3306)/dbname?charsetutf8mb4parseTimeTruelocLocalclient, err : gorm.Open(mysql.Open(dsn), gorm.Config{})if err ! nil {fmt.Println(failed to connect database err.Error())return nil}fmt.Println(db connect success!)return client
}// 根据uid查询订单
func Select(db *gorm.DB, uid string) []MiniprogramOrder {orderList : []MiniprogramOrder{}db.Where(uid ?, uid).Find(orderList)return orderList
}
func main() {var json jsoniter.ConfigCompatibleWithStandardLibrarydb : initMysql()if db nil {return}orderList : Select(db, liupeng20240908)str, _ : json.MarshalToString(orderList)fmt.Println(str)
}2、gorm约定
2.1 使用id作为主键 默认情况下GORM 会使用 ID 作为表的主键。
你可以通过标签 primaryKey 将其它字段设为主键
// 将 UUID 设为主键
type Animal struct {ID int64UUID string gorm:primaryKeyName stringAge int64
}
同时也可以使用复合主键
type Product struct {ID string gorm:primaryKeyLanguageCode string gorm:primaryKeyCode stringName string
}
默认情况下整型 PrioritizedPrimaryField 启用了 AutoIncrement要禁用它您需要为整型字段关闭 autoIncrement
type Product struct {CategoryID uint64 gorm:primaryKey;autoIncrement:falseTypeID uint64 gorm:primaryKey;autoIncrement:false
} 2.2 复数表名
GORM 使用结构体名的 蛇形命名 作为表名。对于结构体MiniprogramOrder根据约定其表名称为miniprogram_orders当然你也可以修改默认表名只需要实现Tabler接口即可
type Tabler interface {TableName() string
}// TableName 会将 User 的表名重写为 new_user
func (User) TableName() string {return new_user
}
2.3 指定表名
我们也可以通过代码指定要访问的表名
db.Table(deleted_users).Where(name ?, jinzhu).Delete(User{})
// DELETE FROM deleted_users WHERE name jinzhu;
2.4 列名
根据约定数据表的列名使用的是 struct 字段名的 蛇形命名
type User struct {ID uint // 列名是 idName string // 列名是 nameBirthday time.Time // 列名是 birthdayCreatedAt time.Time // 列名是 created_at
}
您可以使用 column 标签或 命名策略 来覆盖列名
type Animal struct {AnimalID int64 gorm:column:beast_id // 将列名设为 beast_idBirthday time.Time gorm:column:day_of_the_beast // 将列名设为 day_of_the_beastAge int64 gorm:column:age_of_the_beast // 将列名设为 age_of_the_beast
}
2.5 时间戳追踪
对于有 CreatedAt 字段的模型创建记录时如果该字段值为零值则将该字段的值设为当前时间。
你可以通过将 autoCreateTime 标签置为 false 来禁用时间戳追踪例如
type User struct {CreatedAt time.Time gorm:autoCreateTime:false
}
对于有 UpdatedAt 字段的模型更新记录时将该字段的值设为当前时间。创建记录时如果该字段值为零值则将该字段的值设为当前时间
你可以通过将 autoUpdateTime 标签置为 false 来禁用时间戳追踪例如
type User struct {UpdatedAt time.Time gorm:autoUpdateTime:false
}
了解这些约定后就能够直到第一章节中查询订单函数没有指定表名的原因了。
3、数据库基本操作
3.1 写入数据
数据的写入可以写入单条也可以单次批量写入数据
func Insert(db *gorm.DB, orders []MiniprogramOrder) error {resp : db.Create(orders)if resp.Error ! nil {fmt.Println(resp)return resp.Error}return nil
}
也可以通过db.CreateInBatches方法来指定批量插入的批次大小
func Insert(db *gorm.DB, orders []MiniprogramOrder, size int) error {if size 0 {resp : db.CreateInBatches(orders, size)if resp.Error ! nil {fmt.Println(resp)return resp.Error}} else {resp : db.Create(orders)if resp.Error ! nil {fmt.Println(resp)return resp.Error}}return nil
}
3.2 查询
3.2.1 查询单个对象
// 获取第一条记录主键升序
db.First(user)
// SELECT * FROM users ORDER BY id LIMIT 1;// 获取一条记录没有指定排序字段
db.Take(user)
// SELECT * FROM users LIMIT 1;// 获取最后一条记录主键降序
db.Last(user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;
3.2.2 根据主键检索
db.First(user, 10)
// SELECT * FROM users WHERE id 10;db.First(user, 10)
// SELECT * FROM users WHERE id 10;db.Find(users, []int{1,2,3})
// SELECT * FROM users WHERE id IN (1,2,3);3.2.3 条件检索
// Get first matched record
db.Where(name ?, jinzhu).First(user)
// SELECT * FROM users WHERE name jinzhu ORDER BY id LIMIT 1;// IN
db.Where(name IN ?, []string{jinzhu, jinzhu 2}).Find(users)
// SELECT * FROM users WHERE name IN (jinzhu,jinzhu 2);// LIKE
db.Where(name LIKE ?, %jin%).Find(users)
// SELECT * FROM users WHERE name LIKE %jin%;// AND
db.Where(name ? AND age ?, jinzhu, 22).Find(users)
// SELECT * FROM users WHERE name jinzhu AND age 22;// Time
db.Where(updated_at ?, lastWeek).Find(users)
// SELECT * FROM users WHERE updated_at 2000-01-01 00:00:00;// BETWEEN
db.Where(created_at BETWEEN ? AND ?, lastWeek, today).Find(users)
// SELECT * FROM users WHERE created_at BETWEEN 2000-01-01 00:00:00 AND 2000-01-08 00:00:00;3.2.4 not条件查询
db.Not(name ?, jinzhu).First(user)
// SELECT * FROM users WHERE NOT name jinzhu ORDER BY id LIMIT 1;// Not In
db.Not(map[string]interface{}{name: []string{jinzhu, jinzhu 2}}).Find(users)
// SELECT * FROM users WHERE name NOT IN (jinzhu, jinzhu 2);// Struct
db.Not(User{Name: jinzhu, Age: 18}).First(user)
// SELECT * FROM users WHERE name jinzhu AND age 18 ORDER BY id LIMIT 1;// Not In slice of primary keys
db.Not([]int64{1,2,3}).First(user)
// SELECT * FROM users WHERE id NOT IN (1,2,3) ORDER BY id LIMIT 1;
3.2.5 or条件查询
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, Age: 18}).Find(users)
// SELECT * FROM users WHERE name jinzhu OR (name jinzhu 2 AND age 18);// Map
db.Where(name jinzhu).Or(map[string]interface{}{name: jinzhu 2, age: 18}).Find(users)
// SELECT * FROM users WHERE name jinzhu OR (name jinzhu 2 AND age 18);
3.2.6 select特定字段查询
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;
3.2.7 排序
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;db.Clauses(clause.OrderBy{Expression: clause.Expr{SQL: FIELD(id,?), Vars: []interface{}{[]int{1, 2, 3}}, WithoutParentheses: true},
}).Find(User{})
// SELECT * FROM users ORDER BY FIELD(id,1,2,3)
3.2.8 limit查询
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)db.Offset(3).Find(users)
// SELECT * FROM users OFFSET 3;db.Limit(10).Offset(5).Find(users)
// SELECT * FROM users OFFSET 5 LIMIT 10;// Cancel offset condition with -1
db.Offset(10).Find(users1).Offset(-1).Find(users2)
// SELECT * FROM users OFFSET 10; (users1)
// SELECT * FROM users; (users2)
3.2.9 group by
type result struct {Date time.TimeTotal int
}db.Model(User{}).Select(name, sum(age) as total).Where(name LIKE ?, group%).Group(name).First(result)
// SELECT name, sum(age) as total FROM users WHERE name LIKE group% GROUP BY name LIMIT 1db.Model(User{}).Select(name, sum(age) as total).Group(name).Having(name ?, group).Find(result)
// SELECT name, sum(age) as total FROM users GROUP BY name HAVING name grouprows, err : db.Table(orders).Select(date(created_at) as date, sum(amount) as total).Group(date(created_at)).Rows()
defer rows.Close()
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()
defer rows.Close()
for rows.Next() {...
}type Result struct {Date time.TimeTotal int64
}
db.Table(orders).Select(date(created_at) as date, sum(amount) as total).Group(date(created_at)).Having(sum(amount) ?, 100).Scan(results)3.3 更新
3.3.1 更新单个列
// 根据条件更新
db.Model(User{}).Where(active ?, true).Update(name, hello)
// UPDATE users SET namehello, updated_at2013-11-17 21:34:10 WHERE activetrue;// User 的 ID 是 111
db.Model(user).Update(name, hello)
// UPDATE users SET namehello, updated_at2013-11-17 21:34:10 WHERE id111;// 根据条件和 model 的值进行更新
db.Model(user).Where(active ?, true).Update(name, hello)
// UPDATE users SET namehello, updated_at2013-11-17 21:34:10 WHERE id111 AND activetrue;3.3.2 更新选定列
如果您想要在更新时选择、忽略某些字段您可以使用 Select、Omit
/ 选择 Map 的字段
// User 的 ID 是 111:
db.Model(user).Select(name).Updates(map[string]interface{}{name: hello, age: 18, active: false})
// UPDATE users SET namehello WHERE id111;db.Model(user).Omit(name).Updates(map[string]interface{}{name: hello, age: 18, active: false})
// UPDATE users SET age18, activefalse, updated_at2013-11-17 21:34:10 WHERE id111;// 选择 Struct 的字段会选中零值的字段
db.Model(user).Select(Name, Age).Updates(User{Name: new_name, Age: 0})
// UPDATE users SET namenew_name, age0 WHERE id111;// 选择所有字段选择包括零值字段的所有字段
db.Model(user).Select(*).Updates(User{Name: jinzhu, Role: admin, Age: 0})// 选择除 Role 外的所有字段包括零值字段的所有字段
db.Model(user).Select(*).Omit(Role).Updates(User{Name: jinzhu, Role: admin, Age: 0})
3.3.4 批量更新
如果没有通过 Model 指定一个含有主键的记录GORM 会执行批量更新
// Update with struct
db.Model(User{}).Where(role ?, admin).Updates(User{Name: hello, Age: 18})
// UPDATE users SET namehello, age18 WHERE role admin;// Update with map
db.Table(users).Where(id IN ?, []int{10, 11}).Updates(map[string]interface{}{name: hello, age: 18})
// UPDATE users SET namehello, age18 WHERE id IN (10, 11);
3.4 删除
3.4.1 删除单条记录
删除一条记录时删除对象需要指定主键否则会触发批量删除例如
// Email 的 ID 是 10
db.Delete(email)
// DELETE from emails where id 10;// 带额外条件的删除
db.Where(name ?, jinzhu).Delete(email)
// DELETE from emails where id 10 AND name jinzhu;3.4.2 批量删除
db.Where(email LIKE ?, %jinzhu%).Delete(Email{})
// DELETE from emails where email LIKE %jinzhu%;db.Delete(Email{}, email LIKE ?, %jinzhu%)
// DELETE from emails where email LIKE %jinzhu%;
3.4.3 逻辑删除
如果你的模型包含了 gorm.DeletedAt字段该字段也被包含在gorm.Model中那么该模型将会自动获得软删除的能力
当调用Delete时GORM并不会从数据库中删除该记录而是将该记录的DeleteAt设置为当前时间而后的一般查询方法将无法查找到此条记录。
// users ID is 111
db.Delete(user)
// UPDATE users SET deleted_at2013-10-29 10:23 WHERE id 111;// Batch Delete
db.Where(age ?, 20).Delete(User{})
// UPDATE users SET deleted_at2013-10-29 10:23 WHERE age 20;// Soft deleted records will be ignored when querying
db.Where(age 20).Find(user)
// SELECT * FROM users WHERE age 20 AND deleted_at IS NULL;
被逻辑删除的数据也能通过api可以查找出来
db.Unscoped().Where(age 20).Find(users)
// SELECT * FROM users WHERE age 20;
4、几个钩子函数
Hook 是在创建、查询、更新、删除等操作之前、之后调用的函数。
4.1 创建hook
GORM允许用户通过实现这些接口 BeforeSave, BeforeCreate, AfterSave, AfterCreate来自定义钩子。 这些钩子方法会在创建一条记录时被调用
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {u.UUID uuid.New()if u.Role admin {return errors.New(invalid role)}return
}
4.2 更新hook
GORM 支持的 hook 包括BeforeSave, BeforeUpdate, AfterSave, AfterUpdate. 更新记录时将调用这些方法
func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {if u.Role admin {return errors.New(admin user not allowed to update)}return
}
4.3 删除hook
对于删除操作GORM 支持 BeforeDelete、AfterDelete Hook在删除记录时会调用这些方法
func (u *User) BeforeDelete(tx *gorm.DB) (err error) {if u.Role admin {return errors.New(admin user not allowed to delete)}return
}
5、事务
Gorm 支持直接调用事务控制方法commit、rollback例如
// 开始事务
tx : db.Begin()// 在事务中执行一些 db 操作从这里开始您应该使用 tx 而不是 db
tx.Create(...)// ...// 遇到错误时回滚事务
tx.Rollback()// 否则提交事务
tx.Commit()
示例:
func CreateAnimals(db *gorm.DB) error {// 再唠叨一下事务一旦开始你就应该使用 tx 处理数据tx : db.Begin()defer func() {if r : recover(); r ! nil {tx.Rollback()}}()if err : tx.Error; err ! nil {return err}if err : tx.Create(Animal{Name: Giraffe}).Error; err ! nil {tx.Rollback()return err}if err : tx.Create(Animal{Name: Lion}).Error; err ! nil {tx.Rollback()return err}return tx.Commit().Error
}
6、总结 总之gorm是一个对go开发者非常友好且使用简单的db操作库非常容易上手学习成本很低推荐使用。 上面对操作数据库的基本操作已经介绍的七七八八了完全可以满足日常开发总结出来共享给更多的小伙伴希望对大家有所帮助。