beego 是一个用于Go编程语言的开源、高性能的 web 框架
beego 被用于在Go语言中企业应用程序的快速开发,包括RESTful API、web应用程序和后端服务。它的灵感来源于Tornado, Sinatra 和 Flask
beego 官网:http://beego.gocn.vip/
上面的 beego 官网如果访问不到,看这篇文章《beego 官网文档本地环境搭建》
注意:本文的 beego 文档使用的就是本地环境搭建的文档,因为官网文档已经不可用了
beego 官方 github 仓库:https://github.com/beego/beego
上一讲,讲了 beego ORM 操作数据库,需要的朋友可以查看《Beego 使用教程 9:ORM 操作数据库(上)》
这一讲,继续讲解 ORM 操作数据库。代码使用上一讲的代码
目录
1、Orm 增删改查
如下就可以创建一个简单的Orm
实例
var o orm.Ormer
o = orm.NewOrm() // 创建一个 Ormer
// NewOrm 的同时会执行 orm.BootStrap (整个 app 只执行一次),用以验证模型之间的定义并缓存。
大多数情况下,你应该尽量复用Orm 实例,因为本身Orm实例被设计为无状态的,一个数据库对应一个Orm实例
但是在使用事务的时候,我们会返回TxOrm的实例,它本身是有状态的,一个事务对应一个TxOrm实例。在使用TxOrm时候,任何衍生查询都是在该事务内
1.1、添加
定义
Insert(md interface{}) (int64, error) InsertWithCtx(ctx context.Context, md interface{}) (int64, error)
代码看下面,是上一讲的代码
package dao
import (
"github.com/beego/beego/v2/client/orm"
//匿名引入mysql驱动
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int `orm:"auto"`
Name string `orm:"column(name)"`
Age int `orm:"column(age)"`
}
func init() {
// 注册 User 结构体模型
orm.RegisterModel(new(User))
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(192.168.3.232:3306)/beego-demo-db?charset=utf8")
orm.SetMaxIdleConns("default", 30)
}
func Add() {
o := orm.NewOrm()
user := new(User)
user.Name = "贾元春"
user.Age = 25
// 添加数据
o.Insert(user)
}
1.2、批量添加
InsertMulti(bulk int, mds interface{}) (int64, error) InsertMultiWithCtx(ctx context.Context, bulk int, mds interface{}) (int64, error)
将 user.go 修改为下面代码
package dao
import (
"github.com/beego/beego/v2/client/orm"
//匿名引入mysql驱动
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int `orm:"column(id)"`
Name string `orm:"column(name)"`
Age int `orm:"column(age)"`
}
var o orm.Ormer
func init() {
// 注册 User 结构体模型
orm.RegisterModel(new(User))
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(192.168.3.232:3306)/beego-demo-db?charset=utf8")
orm.SetMaxIdleConns("default", 30)
o = orm.NewOrm()
}
func Add() {
user := new(User)
user.Name = "贾元春"
user.Age = 25
// 添加数据
o.Insert(user)
}
func AddMulti() {
users := [2]User{{Name: "贾迎春", Age: 18}, {Name: "贾惜春", Age: 19}}
o.InsertMulti(2, users)
}
修改 controller 目录下 dao.go 为下面代码
package controller
import (
"beego-demo/dao"
"github.com/beego/beego/v2/server/web"
"github.com/beego/beego/v2/server/web/context"
)
func RegisterDaoRoutes() {
web.Get("/user/add", func(ctx *context.Context) {
dao.Add()
ctx.WriteString("添加成功")
})
web.Get("/user/adds", func(ctx *context.Context) {
dao.AddMulti()
ctx.WriteString("操作成功")
})
}
运行效果
浏览器访问:http://localhost:9090/user/adds
1.3、删除
使用主键来删除数据,定义
Delete(md interface{}, cols ...string) (int64, error) DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error)
第一个返回值是受影响的行数
将 dao 目录下的 user.go 修改为下面代码
package dao
import (
"fmt"
"github.com/beego/beego/v2/client/orm"
//匿名引入mysql驱动
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int `orm:"column(id)"`
Name string `orm:"column(name)"`
Age int `orm:"column(age)"`
}
var o orm.Ormer
func init() {
// 注册 User 结构体模型
orm.RegisterModel(new(User))
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(192.168.3.232:3306)/beego-demo-db?charset=utf8")
orm.SetMaxIdleConns("default", 30)
o = orm.NewOrm()
}
func Add() {
user := new(User)
user.Name = "贾元春"
user.Age = 25
// 添加数据
o.Insert(user)
}
func AddMulti() {
users := [2]User{{Name: "贾迎春", Age: 18}, {Name: "贾惜春", Age: 19}}
o.InsertMulti(2, users)
}
func Delete() {
var user = User{Id: 7}
c, er := o.Delete(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
}
修改 controller 目录下 dao.go 为下面代码
package controller
import (
"beego-demo/dao"
"github.com/beego/beego/v2/server/web"
"github.com/beego/beego/v2/server/web/context"
)
func RegisterDaoRoutes() {
web.Get("/user/add", func(ctx *context.Context) {
dao.Add()
ctx.WriteString("添加成功")
})
web.Get("/user/adds", func(ctx *context.Context) {
dao.AddMulti()
ctx.WriteString("操作成功")
})
web.Get("/user/del", func(ctx *context.Context) {
dao.Delete()
ctx.WriteString("删除成功")
})
}
运行效果
浏览器访问:http://localhost:9090/user/del
1.4、修改
使用主键来更新数据。也就是如果你使用这个方法,Beego 会尝试读取里面的主键值,而后将主键作为更新的条件
定义是
Update(md interface{}, cols ...string) (int64, error) UpdateWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error)
如果你没有指定 cols
参数,那么所有的列都会被更新
第一个返回值是受影响的行数
将 dao 目录下的 user.go 修改为下面代码
package dao
import (
"fmt"
"github.com/beego/beego/v2/client/orm"
//匿名引入mysql驱动
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int `orm:"column(id)"`
Name string `orm:"column(name)"`
Age int `orm:"column(age)"`
}
var o orm.Ormer
func init() {
// 注册 User 结构体模型
orm.RegisterModel(new(User))
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(192.168.3.232:3306)/beego-demo-db?charset=utf8")
orm.SetMaxIdleConns("default", 30)
o = orm.NewOrm()
}
func Add() {
user := new(User)
user.Name = "贾元春"
user.Age = 25
// 添加数据
o.Insert(user)
}
func AddMulti() {
users := [2]User{{Name: "贾迎春", Age: 18}, {Name: "贾惜春", Age: 19}}
o.InsertMulti(2, users)
}
func Delete() {
var user = User{Id: 7}
c, er := o.Delete(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
}
func Update() {
user := User{Id: 6, Name: "贾宝玉", Age: 24}
//默认通过id 更新所有字段
c, er := o.Update(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
user2 := User{Id: 8, Name: "史湘云", Age: 22}
//根据id做条件只更新name字段
o.Update(&user2, "name")
}
修改 controller 目录下 dao.go 为下面代码
package controller
import (
"beego-demo/dao"
"github.com/beego/beego/v2/server/web"
"github.com/beego/beego/v2/server/web/context"
)
func RegisterDaoRoutes() {
web.Get("/user/add", func(ctx *context.Context) {
dao.Add()
ctx.WriteString("添加成功")
})
web.Get("/user/adds", func(ctx *context.Context) {
dao.AddMulti()
ctx.WriteString("操作成功")
})
web.Get("/user/del", func(ctx *context.Context) {
dao.Delete()
ctx.WriteString("删除成功")
})
web.Get("/user/update", func(ctx *context.Context) {
dao.Update()
ctx.WriteString("修改成功")
})
}
运行效果
浏览器访问:http://localhost:9090/user/update
1.5、查询
1.5.1、主键查询
方法定义为
Read(md interface{}, cols ...string) error ReadWithCtx(ctx context.Context, md interface{}, cols ...string) error
该方法的特点是,读取到的数据会被放到 md,
如果传入了 cols
参数,那么只会选取特定的列
将 dao 目录下的 user.go 修改为下面代码
package dao
import (
"fmt"
"github.com/beego/beego/v2/client/orm"
//匿名引入mysql驱动
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int `orm:"column(id)"`
Name string `orm:"column(name)"`
Age int `orm:"column(age)"`
}
var o orm.Ormer
func init() {
// 注册 User 结构体模型
orm.RegisterModel(new(User))
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(192.168.3.232:3306)/beego-demo-db?charset=utf8")
orm.SetMaxIdleConns("default", 30)
o = orm.NewOrm()
}
func Add() {
user := new(User)
user.Name = "贾元春"
user.Age = 25
// 添加数据
o.Insert(user)
}
func AddMulti() {
users := [2]User{{Name: "贾迎春", Age: 18}, {Name: "贾惜春", Age: 19}}
o.InsertMulti(2, users)
}
func Delete() {
var user = User{Id: 7}
c, er := o.Delete(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
}
func Update() {
user := User{Id: 6, Name: "贾宝玉", Age: 24}
//默认通过id 更新所有字段
c, er := o.Update(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
user2 := User{Id: 8, Name: "史湘云", Age: 22}
//根据id做条件只更新name字段
o.Update(&user2, "name")
}
func Find() User {
user := &User{Id: 8}
//通过主键id 查询
o.Read(user)
fmt.Println(user)
return *user
}
修改 controller 目录下 dao.go 为下面代码
package controller
import (
"beego-demo/dao"
"encoding/json"
"github.com/beego/beego/v2/server/web"
"github.com/beego/beego/v2/server/web/context"
)
func RegisterDaoRoutes() {
web.Get("/user/add", func(ctx *context.Context) {
dao.Add()
ctx.WriteString("添加成功")
})
web.Get("/user/adds", func(ctx *context.Context) {
dao.AddMulti()
ctx.WriteString("操作成功")
})
web.Get("/user/del", func(ctx *context.Context) {
dao.Delete()
ctx.WriteString("删除成功")
})
web.Get("/user/update", func(ctx *context.Context) {
dao.Update()
ctx.WriteString("修改成功")
})
web.Get("/user/find", func(ctx *context.Context) {
user := dao.Find()
bytes, _ := json.Marshal(user)
ctx.WriteString("查询成功" + string(bytes))
})
}
运行效果
浏览器访问:http://localhost:9090/user/find
1.5.2、非主键查询
将 dao 目录下的 user.go 修改为下面代码
package dao
import (
"fmt"
"github.com/beego/beego/v2/client/orm"
//匿名引入mysql驱动
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int `orm:"column(id)"`
Name string `orm:"column(name)"`
Age int `orm:"column(age)"`
}
var o orm.Ormer
func init() {
// 注册 User 结构体模型
orm.RegisterModel(new(User))
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(192.168.3.232:3306)/beego-demo-db?charset=utf8")
orm.SetMaxIdleConns("default", 30)
o = orm.NewOrm()
}
func Add() {
user := new(User)
user.Name = "贾元春"
user.Age = 25
// 添加数据
o.Insert(user)
}
func AddMulti() {
users := [2]User{{Name: "贾迎春", Age: 18}, {Name: "贾惜春", Age: 19}}
o.InsertMulti(2, users)
}
func Delete() {
var user = User{Id: 7}
c, er := o.Delete(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
}
func Update() {
user := User{Id: 6, Name: "贾宝玉", Age: 24}
//默认通过id 更新所有字段
c, er := o.Update(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
user2 := User{Id: 8, Name: "史湘云", Age: 22}
//根据id做条件只更新name字段
o.Update(&user2, "name")
}
func Find() User {
//user := &User{Id: 8}
//通过主键id 查询
//o.Read(user)
user := &User{Name: "贾宝玉"}
//非主键查询
o.Read(user, "Name")
fmt.Println(user)
return *user
}
重新运行
2、事务
事务依赖于 Orm
实例
ORM 操作事务,支持两种范式。一种是自己手动管理事务的生命周期;另一种通过闭包的方式,由 Beego 本身来管理事务的生命周期
2.1、手动管理事务
将 dao 目录下的 user.go 修改为下面代码
package dao
import (
"fmt"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
//匿名引入mysql驱动
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int `orm:"column(id)"`
Name string `orm:"column(name)"`
Age int `orm:"column(age)"`
}
var o orm.Ormer
func init() {
// 注册 User 结构体模型
orm.RegisterModel(new(User))
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(192.168.3.232:3306)/beego-demo-db?charset=utf8")
orm.SetMaxIdleConns("default", 30)
o = orm.NewOrm()
}
func Add() {
user := new(User)
user.Name = "贾元春"
user.Age = 25
// 添加数据
o.Insert(user)
}
func AddMulti() {
users := [2]User{{Name: "贾迎春", Age: 18}, {Name: "贾惜春", Age: 19}}
o.InsertMulti(2, users)
}
func Delete() {
var user = User{Id: 7}
c, er := o.Delete(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
}
func Update() {
user := User{Id: 6, Name: "贾宝玉", Age: 24}
//默认通过id 更新所有字段
c, er := o.Update(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
user2 := User{Id: 8, Name: "史湘云", Age: 22}
//根据id做条件只更新name字段
o.Update(&user2, "name")
}
func Find() User {
//user := &User{Id: 8}
//通过主键id 查询
//o.Read(user)
user := &User{Name: "贾宝玉"}
//非主键查询
o.Read(user, "Name")
fmt.Println(user)
return *user
}
// TranAdd 手动管理事务的生命周期
func TranAdd() {
to, err := o.Begin()
if err != nil {
logs.Error("开始事务失败")
return
}
user := User{Name: "北静王", Age: 16}
_, er := to.Insert(user)
if er != nil {
logs.Error("执行事务的sql失败,回滚", er)
//回滚事物
err = to.Rollback()
if err != nil {
logs.Error("回滚失败", err)
}
} else {
//提交事物
err = to.Commit()
if err != nil {
logs.Error("提交失败", err)
}
}
}
修改 controller 目录下 dao.go 为下面代码
package controller
import (
"beego-demo/dao"
"encoding/json"
"github.com/beego/beego/v2/server/web"
"github.com/beego/beego/v2/server/web/context"
)
func RegisterDaoRoutes() {
web.Get("/user/add", func(ctx *context.Context) {
dao.Add()
ctx.WriteString("添加成功")
})
web.Get("/user/adds", func(ctx *context.Context) {
dao.AddMulti()
ctx.WriteString("操作成功")
})
web.Get("/user/del", func(ctx *context.Context) {
dao.Delete()
ctx.WriteString("删除成功")
})
web.Get("/user/update", func(ctx *context.Context) {
dao.Update()
ctx.WriteString("修改成功")
})
web.Get("/user/find", func(ctx *context.Context) {
user := dao.Find()
bytes, _ := json.Marshal(user)
ctx.WriteString("查询成功" + string(bytes))
})
web.Get("/user/tadd", func(ctx *context.Context) {
dao.TranAdd()
ctx.WriteString("添加成功")
})
}
将 user 表name 字段长度改为 25
运行效果
浏览器访问:http://localhost:9090/user/tadd
测试回滚
将 dao 目录下的 user.go 修改为下面代码
package dao
import (
"fmt"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
//匿名引入mysql驱动
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int `orm:"column(id)"`
Name string `orm:"column(name)"`
Age int `orm:"column(age)"`
}
var o orm.Ormer
func init() {
// 注册 User 结构体模型
orm.RegisterModel(new(User))
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(192.168.3.232:3306)/beego-demo-db?charset=utf8")
orm.SetMaxIdleConns("default", 30)
o = orm.NewOrm()
}
func Add() {
user := new(User)
user.Name = "贾元春"
user.Age = 25
// 添加数据
o.Insert(user)
}
func AddMulti() {
users := [2]User{{Name: "贾迎春", Age: 18}, {Name: "贾惜春", Age: 19}}
o.InsertMulti(2, users)
}
func Delete() {
var user = User{Id: 7}
c, er := o.Delete(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
}
func Update() {
user := User{Id: 6, Name: "贾宝玉", Age: 24}
//默认通过id 更新所有字段
c, er := o.Update(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
user2 := User{Id: 8, Name: "史湘云", Age: 22}
//根据id做条件只更新name字段
o.Update(&user2, "name")
}
func Find() User {
//user := &User{Id: 8}
//通过主键id 查询
//o.Read(user)
user := &User{Name: "贾宝玉"}
//非主键查询
o.Read(user, "Name")
fmt.Println(user)
return *user
}
// TranAdd 手动管理事务的生命周期
func TranAdd() {
to, err := o.Begin()
if err != nil {
logs.Error("开始事务失败")
return
}
user := User{Name: "北静王123456789012346578901234564890123456790", Age: 16}
_, er := to.Insert(&user)
if er != nil {
logs.Error("执行事务的sql失败,回滚", er)
//回滚事物
err = to.Rollback()
if err != nil {
logs.Error("回滚失败", err)
}
} else {
//提交事物
err = to.Commit()
if err != nil {
logs.Error("提交失败", err)
}
}
}
运行效果
2.2、闭包的方式管理事务
在这种方式里面,第一个参数是task
,即该事务所有完成的动作。注意的是,如果它返回了 error,那么 Beego 会将整个事务回滚
否则提交事务
另外一个要注意的是,如果在task
执行过程中,发生了panic
,那么 Beego 会回滚事务
我们推荐使用这种方式
将 dao 目录下的 user.go 修改为下面代码
package dao
import (
"fmt"
"context"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
//匿名引入mysql驱动
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int `orm:"column(id)"`
Name string `orm:"column(name)"`
Age int `orm:"column(age)"`
}
var o orm.Ormer
func init() {
// 注册 User 结构体模型
orm.RegisterModel(new(User))
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(192.168.3.232:3306)/beego-demo-db?charset=utf8")
orm.SetMaxIdleConns("default", 30)
o = orm.NewOrm()
}
func Add() {
user := new(User)
user.Name = "贾元春"
user.Age = 25
// 添加数据
o.Insert(user)
}
func AddMulti() {
users := [2]User{{Name: "贾迎春", Age: 18}, {Name: "贾惜春", Age: 19}}
o.InsertMulti(2, users)
}
func Delete() {
var user = User{Id: 7}
c, er := o.Delete(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
}
func Update() {
user := User{Id: 6, Name: "贾宝玉", Age: 24}
//默认通过id 更新所有字段
c, er := o.Update(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
user2 := User{Id: 8, Name: "史湘云", Age: 22}
//根据id做条件只更新name字段
o.Update(&user2, "name")
}
func Find() User {
//user := &User{Id: 8}
//通过主键id 查询
//o.Read(user)
user := &User{Name: "贾宝玉"}
//非主键查询
o.Read(user, "Name")
fmt.Println(user)
return *user
}
// TranAdd 手动管理事务的生命周期
func TranAdd() {
to, err := o.Begin()
if err != nil {
logs.Error("开始事务失败")
return
}
user := User{Name: "北静王123456789012346578901234564890123456790", Age: 16}
_, er := to.Insert(&user)
if er != nil {
logs.Error("执行事务的sql失败,回滚", er)
//回滚事物
err = to.Rollback()
if err != nil {
logs.Error("回滚失败", err)
}
} else {
//提交事物
err = to.Commit()
if err != nil {
logs.Error("提交失败", err)
}
}
}
// TranAdd2 闭包的方式,由 Beego 本身来管理事务的生命周期
func TranAdd2() {
er := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
user := new(User)
user.Name = "贾政"
user.Age = 45
_, e := txOrm.Insert(user)
return e
})
if er != nil {
logs.Error(er)
}
}
修改 controller 目录下 dao.go 为下面代码
package controller
import (
"beego-demo/dao"
"encoding/json"
"github.com/beego/beego/v2/server/web"
"github.com/beego/beego/v2/server/web/context"
)
func RegisterDaoRoutes() {
web.Get("/user/add", func(ctx *context.Context) {
dao.Add()
ctx.WriteString("添加成功")
})
web.Get("/user/adds", func(ctx *context.Context) {
dao.AddMulti()
ctx.WriteString("操作成功")
})
web.Get("/user/del", func(ctx *context.Context) {
dao.Delete()
ctx.WriteString("删除成功")
})
web.Get("/user/update", func(ctx *context.Context) {
dao.Update()
ctx.WriteString("修改成功")
})
web.Get("/user/find", func(ctx *context.Context) {
user := dao.Find()
bytes, _ := json.Marshal(user)
ctx.WriteString("查询成功" + string(bytes))
})
web.Get("/user/tadd", func(ctx *context.Context) {
dao.TranAdd()
ctx.WriteString("添加成功")
})
web.Get("/user/tadd2", func(ctx *context.Context) {
dao.TranAdd2()
ctx.WriteString("添加成功")
})
}
运行效果
浏览器访问:http://localhost:9090/user/tadd2
测试回滚
将 dao 目录下的 user.go 修改为下面代码
package dao
import (
"context"
"fmt"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
//匿名引入mysql驱动
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int `orm:"column(id)"`
Name string `orm:"column(name)"`
Age int `orm:"column(age)"`
}
var o orm.Ormer
func init() {
// 注册 User 结构体模型
orm.RegisterModel(new(User))
orm.RegisterDataBase("default", "mysql", "root:123456@tcp(192.168.3.232:3306)/beego-demo-db?charset=utf8")
orm.SetMaxIdleConns("default", 30)
o = orm.NewOrm()
}
func Add() {
user := new(User)
user.Name = "贾元春"
user.Age = 25
// 添加数据
o.Insert(user)
}
func AddMulti() {
users := [2]User{{Name: "贾迎春", Age: 18}, {Name: "贾惜春", Age: 19}}
o.InsertMulti(2, users)
}
func Delete() {
var user = User{Id: 7}
c, er := o.Delete(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
}
func Update() {
user := User{Id: 6, Name: "贾宝玉", Age: 24}
//默认通过id 更新所有字段
c, er := o.Update(&user)
if er != nil {
fmt.Println(er)
}
fmt.Println(c)
user2 := User{Id: 8, Name: "史湘云", Age: 22}
//根据id做条件只更新name字段
o.Update(&user2, "name")
}
func Find() User {
//user := &User{Id: 8}
//通过主键id 查询
//o.Read(user)
user := &User{Name: "贾宝玉"}
//非主键查询
o.Read(user, "Name")
fmt.Println(user)
return *user
}
// TranAdd 手动管理事务的生命周期
func TranAdd() {
to, err := o.Begin()
if err != nil {
logs.Error("开始事务失败")
return
}
user := User{Name: "北静王123456789012346578901234564890123456790", Age: 16}
_, er := to.Insert(&user)
if er != nil {
logs.Error("执行事务的sql失败,回滚", er)
//回滚事物
err = to.Rollback()
if err != nil {
logs.Error("回滚失败", err)
}
} else {
//提交事物
err = to.Commit()
if err != nil {
logs.Error("提交失败", err)
}
}
}
// TranAdd2 闭包的方式,由 Beego 本身来管理事务的生命周期
func TranAdd2() {
er := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
user := new(User)
user.Name = "贾政123456789012345678901234567890"
user.Age = 45
_, e := txOrm.Insert(user)
return e
})
if er != nil {
logs.Error(er)
}
}
运行效果
3、QueryBuilder 构造复杂查询
QueryBuilder 提供了一个简便,流畅的 SQL 查询构造器。在不影响代码可读性的前提下用来快速的建立 SQL 语句。
QueryBuilder 在功能上与 ORM 重合, 但是各有利弊。ORM 更适用于简单的 CRUD 操作,而 QueryBuilder 则更适用于复杂的查询,例如查询中包含子查询和多重联结
在 dao 目录下新建 user2.go,代码是下面内容
package dao
import (
"fmt"
"github.com/beego/beego/v2/client/orm"
)
func SelectUser() []User {
qb, er := orm.NewQueryBuilder("mysql")
if er != nil {
panic(er)
}
qb.Select("id", "name").From("user").Where("id > ?")
sql := qb.String()
fmt.Println(sql)
var users []User
o.Raw(sql, 10).QueryRows(&users)
return users
}
修改 controller 目录下 dao.go 为下面代码
package controller
import (
"beego-demo/dao"
"encoding/json"
"github.com/beego/beego/v2/server/web"
"github.com/beego/beego/v2/server/web/context"
)
func RegisterDaoRoutes() {
web.Get("/user/add", func(ctx *context.Context) {
dao.Add()
ctx.WriteString("添加成功")
})
web.Get("/user/adds", func(ctx *context.Context) {
dao.AddMulti()
ctx.WriteString("操作成功")
})
web.Get("/user/del", func(ctx *context.Context) {
dao.Delete()
ctx.WriteString("删除成功")
})
web.Get("/user/update", func(ctx *context.Context) {
dao.Update()
ctx.WriteString("修改成功")
})
web.Get("/user/find", func(ctx *context.Context) {
user := dao.Find()
bytes, _ := json.Marshal(user)
ctx.WriteString("查询成功" + string(bytes))
})
web.Get("/user/tadd", func(ctx *context.Context) {
dao.TranAdd()
ctx.WriteString("添加成功")
})
web.Get("/user/tadd2", func(ctx *context.Context) {
dao.TranAdd2()
ctx.WriteString("添加成功")
})
web.Get("/user/select", func(ctx *context.Context) {
users := dao.SelectUser()
//返回json
ctx.Output.JSON(users, false, false)
})
}
返回 json
运行效果,浏览器访问:http://localhost:9090/user/select
4、QuerySeter 复杂查询
ORM 以 QuerySeter 来组织查询,每个返回 QuerySeter 的方法都会获得一个新的 QuerySeter 对象
基本使用方法
o := orm.NewOrm() // 获取 QuerySeter 对象,user 为表名 qs := o.QueryTable("user") // 也可以直接使用 Model 结构体作为表名 qs = o.QueryTable(&User) // 也可以直接使用对象作为表名 user := new(User) qs = o.QueryTable(user) // 返回 QuerySeter // 后面可以调用qs上的方法,执行复杂查询。
修改 dao 目录下 user2.go 为下面内容
package dao
import (
"fmt"
"github.com/beego/beego/v2/client/orm"
)
func SelectUser() []User {
qb, er := orm.NewQueryBuilder("mysql")
if er != nil {
panic(er)
}
qb.Select("id", "name").From("user").Where("id > ?")
sql := qb.String()
fmt.Println(sql)
var users []User
o.Raw(sql, 10).QueryRows(&users)
return users
}
func SelectUser2() User {
o := orm.NewOrm()
qs := o.QueryTable("user")
var user User
qs.Filter("id", 14).One(&user)
return user
}
修改 controller 目录下 dao.go 为下面代码
package controller
import (
"beego-demo/dao"
"encoding/json"
"github.com/beego/beego/v2/server/web"
"github.com/beego/beego/v2/server/web/context"
)
func RegisterDaoRoutes() {
web.Get("/user/add", func(ctx *context.Context) {
dao.Add()
ctx.WriteString("添加成功")
})
web.Get("/user/adds", func(ctx *context.Context) {
dao.AddMulti()
ctx.WriteString("操作成功")
})
web.Get("/user/del", func(ctx *context.Context) {
dao.Delete()
ctx.WriteString("删除成功")
})
web.Get("/user/update", func(ctx *context.Context) {
dao.Update()
ctx.WriteString("修改成功")
})
web.Get("/user/find", func(ctx *context.Context) {
user := dao.Find()
bytes, _ := json.Marshal(user)
ctx.WriteString("查询成功" + string(bytes))
})
web.Get("/user/tadd", func(ctx *context.Context) {
dao.TranAdd()
ctx.WriteString("添加成功")
})
web.Get("/user/tadd2", func(ctx *context.Context) {
dao.TranAdd2()
ctx.WriteString("添加成功")
})
web.Get("/user/select", func(ctx *context.Context) {
users := dao.SelectUser()
//返回json
ctx.Output.JSON(users, false, false)
})
web.Get("/user/select2", func(ctx *context.Context) {
user := dao.SelectUser2()
//返回json
ctx.Output.JSON(user, false, false)
})
}
运行效果
浏览器访问:http://localhost:9090/user/select2
5、原生查询
大多数时候,你都不应该使用原生查询。只有在无可奈何的情况下才应该考虑原生查询。使用原生查询可以,无需使用 ORM 表定义;多数据库,都可直接使用占位符号 ?
,自动转换;查询时的参数,支持使用 Model Struct 和 Slice, Array
例如
o := orm.NewOrm() ids := []int{1, 2, 3} var r RawSter r = o.Raw("SELECT name FROM user WHERE id IN (?, ?, ?)", ids)
修改 dao 目录下 user2.go 为下面内容
package dao
import (
"fmt"
"github.com/beego/beego/v2/client/orm"
)
func SelectUser() []User {
qb, er := orm.NewQueryBuilder("mysql")
if er != nil {
panic(er)
}
qb.Select("id", "name").From("user").Where("id > ?")
sql := qb.String()
fmt.Println(sql)
var users []User
o.Raw(sql, 10).QueryRows(&users)
return users
}
func SelectUser2() User {
o := orm.NewOrm()
qs := o.QueryTable("user")
var user User
qs.Filter("id", 14).One(&user)
return user
}
// SelectUser3 原生查询
func SelectUser3() []User {
var users []User
ids := []int{13, 14, 15}
r := o.Raw("SELECT id, name, age FROM user WHERE id IN (?, ?, ?)", ids)
r.QueryRows(&users)
//执行
res, er := r.Exec()
if er != nil {
panic(er)
}
nums, err := res.RowsAffected()
if err != nil {
panic(err)
}
fmt.Println(nums)
return users
}
修改 controller 目录下 dao.go 为下面代码
package controller
import (
"beego-demo/dao"
"encoding/json"
"github.com/beego/beego/v2/server/web"
"github.com/beego/beego/v2/server/web/context"
)
func RegisterDaoRoutes() {
web.Get("/user/add", func(ctx *context.Context) {
dao.Add()
ctx.WriteString("添加成功")
})
web.Get("/user/adds", func(ctx *context.Context) {
dao.AddMulti()
ctx.WriteString("操作成功")
})
web.Get("/user/del", func(ctx *context.Context) {
dao.Delete()
ctx.WriteString("删除成功")
})
web.Get("/user/update", func(ctx *context.Context) {
dao.Update()
ctx.WriteString("修改成功")
})
web.Get("/user/find", func(ctx *context.Context) {
user := dao.Find()
bytes, _ := json.Marshal(user)
ctx.WriteString("查询成功" + string(bytes))
})
web.Get("/user/tadd", func(ctx *context.Context) {
dao.TranAdd()
ctx.WriteString("添加成功")
})
web.Get("/user/tadd2", func(ctx *context.Context) {
dao.TranAdd2()
ctx.WriteString("添加成功")
})
web.Get("/user/select", func(ctx *context.Context) {
users := dao.SelectUser()
//返回json
ctx.Output.JSON(users, false, false)
})
web.Get("/user/select2", func(ctx *context.Context) {
user := dao.SelectUser2()
//返回json
ctx.Output.JSON(user, false, false)
})
web.Get("/user/select3", func(ctx *context.Context) {
users := dao.SelectUser3()
//返回json
ctx.Output.JSON(users, false, false)
})
}
运行效果
浏览器访问:http://localhost:9090/user/select3
更多详情用法请查阅 Beego 官方文档
至此完