GoFrame day5
前言
有了客户端与服务端的请求和处理之后,我们还需要完成一些其他的功能,比如数据库交互,国际化服务,资源管理,分页管理…
今天就来学习一下重要的数据库交互相关内容,说到底大多数服务也只是对数据库进行增删改查.在GoFramev2.1之后数据库驱动都需要手动引入,相关的操作可以去看看这里github.com/gogf/gf/tre…
ORM
GoFrame的ORM功能使用gdb
模块实现,采用了链接池设计所以会自动关闭不再需要手动关闭.
使用配置
首先连接数据库需要设置数据库类型,数据库名,数据库链接(用户名,密码…),和之前的配置文件类似,同样可以在config.yaml
中设置这些参数
增删改查相关
一般常用的数据库操作可以使用GoFrame支持的ORM链式操作,但是默认情况下gdb
都不是链式安全的,也就是说每一个方法都会对当前的Model
进行修改,不能重复使用.我们也可以手动调用Clone
来克隆当前的模型,创建一个新的模型来实现链式安全.也可以设置Safe
设置当前为链式安全的,不过每一次操作都需要使用变量赋值来覆盖原始模型.
对于较为复杂不好组合的查询或者操作,则可以选择使用原生的数据库操作来实现.下面就来看看一些例子(以插入insert
为例)
package main import ( "fmt" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/frame/g" ) type User struct { Uid int `orm:"uid"` Name string `orm:"name"` Site string `orm:"site"` } func main() { user := &User{ Uid: 1, Name: "john", Site: "https://goframe.org", } db := g.DB() var ctx = gctx.New() g.Model("user").Data(user).Insert() _, err := db.Insert(ctx, "user", g.Map{ "name": "bbb", }) if err != nil { println(err) } g.Model("user").Data(g.Map{ "name": "ccc", }).Insert() g.Model("user").Data(g.Map{ "name": "ddd", }).Insert() //数量 count, err := g.DB().Model("user").Where("uid", 10001).Count() if err != nil { panic(err) } fmt.Println("count:", count) //获取单个值 v, err := g.DB().Model("user").Where("uid", 10000).Fields("name").Value() if err != nil { panic(err) } fmt.Println("name:", v.String()) // 查询对象 r, err := g.DB().Model("user").Where("uid", 10001).One() if err != nil { panic(err) } fmt.Println("name:", r.Map()["name"]) // 查询对象 //l, err := g.DB().Model("user").As("t").Where("t.uid > ?", 10000).All() // 也可以简写为 select * from user as t where t.uid > 10000 l, err := g.DB().Model("user").As("t").All("t.uid > ?", 10000) if err != nil { panic(err) } for index, value := range l { fmt.Println(index, value["uid"], value["name"]) } //g.DB().Model("user").Where("uid", 10001).Delete() //g.DB().Model("user").Where("uid", 10002).Delete() } 复制代码
对于简单的操作,可以使用g.Model()
调用链式方法,默认Model
使用的是config.yaml
中default的设置,我的配置如下:
debug
可以让我们看到每一行语句是否成功,dryrun: 0
不会让我们只读不写,其他设置都是数据库连接相关,当然也可以添加log方便以后检查.
从代码看我们添加数据有好几种方式:
- 链式添加一个实体对象
- 链式添加一个
g.Map{}
封装的数据 - 原生方式添加一个数据
其他操作,如查询删除等等都可以仿照这份代码里的操作进行
事务与闭包
常规的事务操作方法为Begin/Commit/Rollback
,先用Begin
开启事务返回一个事务的操作对象;然后对操作对象进行后续数据库操作,利用Commit
提交事务,如果存在错误就使用Callback
回滚.但是开启事务之后一定要记得进行事务的提交或者回滚,否则会导致goroutine
不断增长,导致后续事务超时.
为了防止我们忘记提交或者回滚,所以建议使用闭包操作处理事务.当给定的闭包方法没有错误的时候会自动执行提交事务,反之则会回滚事务.