gorm是什么?
ORM-Object-Relationl Mapping,即對(duì)象關(guān)系映射,這里的Relationl指的是關(guān)系型數(shù)據(jù)庫它的作用是在關(guān)系型數(shù)據(jù)庫和對(duì)象之間作一個(gè)映射,這樣,我們?cè)诰唧w的操作數(shù)據(jù)庫的時(shí)候,就不需要再去和復(fù)雜的SQL語句打交道,只要像平時(shí)操作對(duì)象一樣操作它就可以了GORM就是go語言實(shí)現(xiàn)的一個(gè)ORM庫特點(diǎn):
全特性 ORM (幾乎包含所有特性)
模型關(guān)聯(lián) (一對(duì)一, 一對(duì)多,一對(duì)多(反向), 多對(duì)多, 多態(tài)關(guān)聯(lián))
鉤子 (Before/After Create/Save/Update/Delete/Find)
預(yù)加載
事務(wù)
復(fù)合主鍵
SQL 構(gòu)造器
自動(dòng)遷移
日志
基于GORM回調(diào)編寫可擴(kuò)展插件
全特性測(cè)試覆蓋
開發(fā)者友好
GORM之簡(jiǎn)單CRUD
增加(Create)
user := User{Name: “Jinzhu”, Age: 18, Birthday: time.Now()}db.NewRecord(user) // => 返回 `true` ,因?yàn)橹麈I為空db.Create(&user)db.NewRecord(user) // => 在 `user` 之后創(chuàng)建返回 `false`
檢索(Retrieve)
// 獲取第一條記錄,按主鍵排序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;// 獲取所有的記錄db.Find(&users)//// SELECT * FROM users;// 通過主鍵進(jìn)行查詢 (僅適用于主鍵是數(shù)字類型)db.First(&user, 10)//// SELECT * FROM users WHERE id = 10;
更新(Update)
db.First(&user)user.Name = “jinzhu 2″user.Age = 100db.Save(&user)// 如果單個(gè)屬性被更改了,更新它db.Model(&user).Update(“name”, “hello”)//// UPDATE users SET name=’hello’, updated_at=’2013-11-17 21:34:10′ WHERE id=111;// 使用組合條件更新單個(gè)屬性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;
刪除(Delete)
// 刪除一條存在的記錄db.Delete(&email)//// DELETE from emails where id=10;// 為刪除 SQL 語句添加額外選項(xiàng)db.Set(“gorm:delete_option”, “OPTION (OPTIMIZE FOR UNKNOWN)”).Delete(&email)//// DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN);
如果模型中有 DeletedAt 字段,它將自動(dòng)擁有軟刪除的能力!當(dāng)執(zhí)行刪除操作時(shí),數(shù)據(jù)并不會(huì)永久的從數(shù)據(jù)庫中刪除,而是將 DeletedAt 的值更新為當(dāng)前時(shí)間。具體的使用可查看gorm 官方文檔
項(xiàng)目中聲明全局GVA_DB
在項(xiàng)目中我們定義一個(gè)全局的GVA_DB,方便使用時(shí)調(diào)用
// global.govar ( GVA_DB *gorm.DB )
后續(xù)我們?cè)谛枰樵償?shù)據(jù)庫時(shí)便可直接通過global.GVA_DB使用比如創(chuàng)建商品信息:我們先通過查詢分類是否存在,然后再創(chuàng)建商品
func (m *ManageGoodsInfoService) CreateMallGoodsInfo(req manageReq.GoodsInfoAddParam) (err error) { var goodsCategory manage.MallGoodsCategory err = global.GVA_DB.Where(“category_id=? AND is_deleted=0”, req.GoodsCategoryId).First(&goodsCategory).Error if goodsCategory.CategoryLevel != enum.LevelThree.Code() { return errors.New(“分類數(shù)據(jù)異常”) } if !errors.Is(global.GVA_DB.Where(“goods_name=? AND goods_category_id=?”, req.GoodsName, req.GoodsCategoryId).First(&manage.MallGoodsInfo{}).Error, gorm.ErrRecordNotFound) { return errors.New(“已存在相同的商品信息”) }…… err = global.GVA_DB.Create(&goodsInfo).Error return err}
通過gorm的鏈?zhǔn)讲僮骺梢院芊奖愕倪M(jìn)行crud操作
分頁查詢
分頁查詢是項(xiàng)目中經(jīng)常使用到的功能,當(dāng)指定條件查詢的數(shù)據(jù)量過大時(shí),如果我們將數(shù)據(jù)一次性返回,會(huì)對(duì)數(shù)據(jù)庫造成較大的負(fù)荷,同時(shí)降低接口的性能,通常我們會(huì)使用分頁查詢的方式讓數(shù)據(jù)進(jìn)行分段展示,從而保障接口的性能。在gorm中我們實(shí)用Offset,和Count來實(shí)現(xiàn)分頁
Offset 指定在開始返回記錄之前要跳過的記錄數(shù)。
db.Offset(3).Find(&users)//// SELECT * FROM users OFFSET 3;// 用 -1 取消 OFFSET 限制條件db.Offset(10).Find(&users1).Offset(-1).Find(&users2)//// SELECT * FROM users OFFSET 10; (users1)//// SELECT * FROM users; (users2)
Count 獲取模型記錄數(shù)。注意:在查詢鏈中使用 Count 時(shí),必須放在最后一個(gè)位置,因?yàn)樗鼤?huì)覆蓋 SELECT 查詢條件。
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’;
我們通過前端的傳遞過來的分頁數(shù)據(jù)進(jìn)行查詢
func (m *ManageGoodsInfoService) GetMallGoodsInfoInfoList(info manageReq.MallGoodsInfoSearch, goodsName string, goodsSellStatus string) (err error, list interface{}, total int64) { limit := info.PageSize offset := info.PageSize * (info.PageNumber – 1) // 創(chuàng)建db db := global.GVA_DB.Model(&manage.MallGoodsInfo{}) var mallGoodsInfos []manage.MallGoodsInfo // 如果有條件搜索 下方會(huì)自動(dòng)創(chuàng)建搜索語句 err = db.Count(&total).Error if err != nil { return } if goodsName != “” { db.Where(“goods_name =?”, goodsName) } if goodsSellStatus != “” { db.Where(“goods_sell_status =?”, goodsSellStatus) } err = db.Limit(limit).Offset(offset).Order(“goods_id desc”).Find(&mallGoodsInfos).Error return err, mallGoodsInfos, total}
總結(jié)
該商城作為gin的學(xué)習(xí)項(xiàng)目,沒有很復(fù)雜的邏輯,所有業(yè)務(wù)邏輯均通過Mysql實(shí)現(xiàn)。包括后面將要介紹的登錄態(tài),也是如此。所有代碼已上傳github,有興趣的可以訪問https://github.com/newbee-ltd/newbee-mall-api-go/,如果有更好的建議也歡迎提交issure,pr