GoFrame ORM 使用实践分享
前言
本月会持续更新Go语言相关的文章,尤其是GoFrame,感兴趣的同学可以关注我,结伴而行。
同时会沉淀总结一下:《中台开发实践》、《私有化部署实践》、《深入理解goroutine及使用实践》、《如何在开发过程中把GO语言的价值体现出来》。
立志沉淀一些质量高的内容出来。
今天这篇把我使用GoFrame ORM
的过程中认为有价值、可能踩坑、比较好的实践等相关的知识点分享出来。
值类型和指针类型
初学go的时候一直在纠结值类型和指针类型,后来在用的过程中发现大可不必纠结。
指针类型的优势就是节省内存空间,多个变量指向同一个内存地址,一荣俱荣,一个修改,处处修改。
而值类型可以简单理解为:避免这种一处修改处处修改的问题,有些场景下我们不能单纯的考虑性能,不能单纯地只考虑复用
。
在GoFrame中也鼓励我们使用指针类型,举个栗子:
使用Scan
将查询结果转换成struct
对象
Scan
支持将查询结果转换为一个struct
对象,查询结果应当是特定的一条记录,并且pointer
参数应当为struct
对象的指针地址(*struct
或者**struct
),使用方式例如:
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
user := User{}
g.Model("user").Where("id", 1).Scan(&user)
或者
var user = User{}
g.Model("user").Where("id", 1).Scan(&user)
前两种方式都是预先初始化对象(提前分配内存)
推荐的方式如下,这种方式只有在查询到数据的时候才会执行初始化及内存分配:
var user *User
g.Model("user").Where("id", 1).Scan(&user)
注意在用法上的区别,特别是传递参数类型的差别(前两种方式传递的参数类型是*User
,这里传递的参数类型其实是**User
)。
插入数据
InsertIgnore
这个函数需要重点和大家说一下,因为我之前有Laravel的使用经验,Laravel中的InsertIgnore
是配合唯一索引使用,意思是如果存在唯一主键或者唯一索引就忽略掉,不重复插入。
在GoFrame中是相反的:
GoFrame中默认的insert
函数,就会根据唯一索引(或主键)执行,如果有存在的数据返回失败,不重复插入。
而GoFrame中的InsertIgnore是忽略错误继续插入,而不是存在就不插入。
大家在使用中要注意。
灵活执行SQL
我们要拼接自定义的sql参数怎么办法呢?
gdb.Raw()
示例如下:
OnDuplicate(g.Map{
"nickname": gdb.Raw("CONCAT('name_', VALUES(`nickname`))"),
})
gdb.Raw()
中的参数将作为sql执行的语句,不会自动转换成字符串类型,也不会作为预处理参数。
示例如下:
// INSERT INTO `user`(`id`,`passport`,`password`,`nickname`,`create_time`) VALUES(id+2,'80','123456','wzy',now())
g.Model("user").Data(g.Map{
"id": gdb.Raw("id+2"),
"passport": "80",
"password": "123456",
"nickname": "wzy",
"create_time": gdb.Raw("now()"),
}).Insert()
链式安全
我们首先要有这个概念:什么是链式安全?
其实很简单:链式安全就是操作model模型时不会改变当前model对象,模型属性修改/条件叠加需要使用赋值来操作。
而链式非安全
或者非链式安全
就是:操作model模型时会改变当前model对象的属性。
在GoFrame开发过程中,强烈建议使用gf gen dao
生成的model和dao文件!!!
通过gf gen dao
生成的model和dao文件默认是链式安全的。
举例如下:
func NewGomeStockDao() *GomeStockDao {
return &GomeStockDao{
M: g.DB("default").Model("gome_stock").Safe(), //注意看这里
DB: g.DB("default"),
Table: "gome_stock",
Columns: gomeStockColumns{
Id: "id",
MchWhseCode: "mch_whse_code",
MchWhseName: "mch_whse_name",
IsNationWide: "is_nation_wide",
Status: "status",
LastUpateTime: "last_upate_time",
},
}
}
链式安全时我们如何叠加条件改变呢?
答案就是:通过赋值。
链式安全时通过 m = m.xxx 方式赋值实现链式调用
举例如下:
m := user.Where("status IN(?)", g.Slice{1,2,3})
if vip {
// 查询条件通过赋值叠加
m = m.And("money>=?", 1000000)
} else {
// 查询条件通过赋值叠加
m = m.And("money<?", 1000000)
}
// vip: SELECT * FROM user WHERE status IN(1,2,3) AND money >= 1000000
// !vip: SELECT * FROM user WHERE status IN(1,2,3) AND money < 1000000
r, err := m.All()
// vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money >= 1000000
// !vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money < 1000000
n, err := m.Count()
总结
碰到好的东西就忍不住分享,我现在可以说是Go语言的忠实拥趸。
对GO感兴趣的朋友可以查看我之前写的文章,了解一下Go的魅力:
欢迎大家关注我的Go语言学习专栏
,我会持续更新在Go学习和使用过程中的干货分享。
最后
感谢阅读,欢迎大家三连:点赞、收藏、投币(关注)!!!
转载自:https://juejin.cn/post/7082278651681013773