前言

本文中研究学习beego对于数据库的增删查改。beego的官方ORM DEMO不是很好,demo无法跑通,也无法自动创建表结构。因此,本文重新设计了学习流程。

环境准备
go get github.com/astaxie/beego/orm

2、安装驱动

1
2
3
go get -u github.com/mattn/go-sqlite3
go get -u github.com/go-sql-driver/mysql
go get -u github.com/lib/pq
First Model

本节中创建一个名为User的Model,只有三个字段,Id、Name和Age。运行代码,创建sqlite数据库和user表结构,并且向user表中插入一条数据。

1、在vkbeego/models目录中创建main.go文件,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package main

import (
"fmt"
"github.com/astaxie/beego/orm"
_ "vkbeego/routers"
//_ "github.com/go-sql-driver/mysql"
_ "github.com/mattn/go-sqlite3"
)

type User struct {
Id int
Name string
Age int
}

func create_table(){
// 数据库别名
name := "default"

// drop table 后再建表
force := true

// 打印执行过程
verbose := true

// 遇到错误立即返回
err := orm.RunSyncdb(name, force, verbose)
if err != nil {
fmt.Println(err)
}
}

func init() {
//orm.RegisterDriver("mysql", orm.DRMySQL)
//orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8")
orm.RegisterDriver("sqlite3", orm.DRSqlite)
orm.RegisterDataBase("default", "sqlite3", "db.sqlite3")
orm.RegisterModel(new(User))
create_table()
}

func main() {
o := orm.NewOrm()
o.Using("default") // 默认使用 default,你可以指定为其他数据库

user := new(User)
user.Name = "Hankin"

fmt.Println(o.Insert(user))

}
go run main.go

3、查看执行效果
查看vkbeego/models目录,发现出现了db.sqlite3文件。如果运行代码时右键run,那么db.sqlite3文件会出现在根目录下。
使用navicat for sqlite,打开db.sqlite3数据库,可以看到创建的表和数据。

增加数据

以上,已经实现了向数据库中添加数据,但是,Model的定义和注册、数据库的连接、插入数据的逻辑都在同一个文件中,非常混乱。因此需要对代码进行拆分,调整结构。

1、删除First Model
删除models目录下的main.go和db.sqlite3。

2、在models目录下新建models.go,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package models

import (
"fmt"
"github.com/astaxie/beego/orm"
_ "github.com/mattn/go-sqlite3"
)

type User struct {
Id int
Username string
Password string
}

func create_table(){
// 数据库别名
name := "default"

// drop table 后再建表
force := false

// 打印执行过程
verbose := true

// 遇到错误立即返回
err := orm.RunSyncdb(name, force, verbose)
if err != nil {
fmt.Println(err)
}
}

func init() {
orm.RegisterModel(new(User))
orm.RegisterDriver("sqlite3", orm.DRSqlite)
orm.RegisterDataBase("default", "sqlite3", "db.sqlite3")
create_table()
}

3、在routers/user.go中添加路由:

1
beego.Router("/user/add", &user.AddController{})

4、在controllers/user目录中新建文件add.go,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package user

import (
"fmt"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
"vkbeego/models"
)

type AddController struct {
beego.Controller
}

func (c *AddController) Get() {
var username = c.GetString("username")
fmt.Println(username)
c.Ctx.WriteString("Please add user by post request.")
}

func (c *AddController) Post() {
var username = c.GetString("username")
var password = c.GetString("password")
//fmt.Println(username)
//fmt.Println(password)
var o = orm.NewOrm()
o.Using("default")
var user = new(models.User)
user.Username = username
user.Password = password
o.Insert(user)
c.Ctx.WriteString("add user: " + username)

}

5、测试
启动beego,使用Postman,发送Post请求到 http://localhost:8080/user/add ,请求参数包括username和password,成功写入参数到数据库。

查看数据

1、在routers/user.go中添加路由:

1
beego.Router("/user/list", &user.ListController{})

2、在controllers/user目录中新建文件list.go,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package user

import (
"fmt"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
"vkbeego/models"
)

type ListController struct {
beego.Controller
}

func (c *ListController) Get() {
var o = orm.NewOrm()
o.Using("default")
var qs orm.QuerySeter
qs = o.QueryTable("user")
var users []*models.User
//num, err := qs.All(&users)
num, err := qs.All(&users,"Id", "Username")
fmt.Printf("Returned Rows Num: %d, %s \n", num, err)
fmt.Println(users[0].Username)
c.Data["users"] = users
c.TplName = "user/list.tpl"
}

3、在views/user目录中新建list.tpl文件,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>User List</title>
</head>
<body>
<h2>User List</h2>
{{range .users}}
<p>
ID为:{{.Id}},用户名为:{{.Username}}
</p>
{{end}}

{{range $index,$user := .users}}
<p>
Index为:{{$index}},ID为:{{$user.Id}},用户名为:{{$user.Username}}
</p>
{{end}}

</body>
</html>

4、测试
启动beego,使用Postman,发送Get请求到 http://localhost:8080/user/list ,即可看到用户列表。

修改数据

1、在routers/user.go中添加路由:

1
beego.Router("/user/update", &user.UpdateController{})

2、在controllers/user目录中新建文件update.go,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package user

import (
"fmt"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
"vkbeego/models"
)

type UpdateController struct {
beego.Controller
}

func (c *UpdateController) Get() {
c.Ctx.WriteString("Please use post request.")
}


func (c *UpdateController) Post() {
//id,_ := c.GetInt("id")
username := c.GetString("username")
password := c.GetString("password")
new_password := c.GetString("new_password")

var o = orm.NewOrm()
o.Using("default")

exist := o.QueryTable("user").Filter("UserName", username).Exist()
if !exist{
c.Ctx.WriteString("Username doesn't exist!")
return;
}

var user models.User
o.QueryTable("user").Filter("Username",username).Filter("Password",password).One(&user)

if o.Read(&user) == nil {
user.Password = new_password
if num, err := o.Update(&user); err == nil {
fmt.Println(num)
}
}else {
c.Ctx.WriteString("Username or password is wrong!")
return;
}

c.Ctx.WriteString("Password has been updated!")
}

3、测试
启动beego,使用Postman,发送Post请求到 http://localhost:8080/user/update 进行密码的更新,请求参数包括username、password和new_password。

删除数据

1、在routers/user.go中添加路由:

1
beego.Router("/user/del", &user.DelController{})

2、在controllers/user目录中新建文件del.go,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package user

import (
"fmt"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
)

type DelController struct {
beego.Controller
}

func (c *DelController) Get() {
c.Ctx.WriteString("Please use post request.")
}

func (c *DelController) Post() {
id,_ := c.GetInt("id")

var o = orm.NewOrm()
o.Using("default")

num,err := o.QueryTable("user").Filter("Id",id).Delete()
fmt.Printf("Returned Rows Num: %d, %s \n", num, err)
if num != 0 {
c.Ctx.WriteString("User has been deleted!")
}else{
c.Ctx.WriteString("User Id doesn't exist! Can't delete!")
}
}

3、测试
启动beego,使用Postman,发送Post请求到 http://localhost:8080/user/del 进行删除数据,请求参数为id。

结构体和表

上面的代码中,我们并没有指定结构体和数据库表的对应关系,那么它们是怎样关联起来的呢?
参考beego框架之orm模块——mysql、BeegoOrm 映射自定义表名以及自定义字段,可知在beego的models模块里,会自动处理结构体和数据库表的对应关系,比如:

1
2
3
4
5
type User struct{    // 默认情况对应数据库的表名为:user
MyName string // 默认情况对应数据库里user表字段为:my_name
MyAge string // 默认情况对应数据库里user表字段为:my_age
}
orm.RegisterModel(new(User))

新的需求:
结构体名为User对应数据库的表名为test_user
MyName的成员对应数据库的字段名为MyName
MyAge的成员对应数据库的字段名为MyAge

那么该User的结构体又该如何定义呢?新需求的User结构体:

1
2
3
4
5
6
7
8
9
10
type User struct{
MyName string `orm:"column(MyName)"`
MyAge string `orm:"column(MySex)"`
}
orm.RegisterModel(new(User))

// 自定义表名(系统自动调用)
func (u *User) TableName() string {
return "test_user"
}
后记

至此,beego的增删查改操作基本都已经涉及,更高级的查询在使用时再去学习。

源码分享:v0.0.1

书签