pop 的基础使用。
pop是gobuffalo默认的orm包,当然也可以在其他项目使用pop。但是pop官方强调自己不是orm,只是具备orm的功能。其主要的优点就是:
- 支持CRUD操作
- 代码定义模型
- 用于创建,删除和修改的迁移工具
- 数据库支持:PostgreSQL,MySQL,SQLite
- ActiveRecord UUID模式
- YAML配置
- 易于环境变量使用
- 创建和更新每条记录的时间戳
- 支持事务
安装
$ go get github.com/gobuffalo/pop/...
$ go install github.com/gobuffalo/pop/soda
配置
配置文件默认在config/database.yaml
development:
dialect: "mysql"
database: "cokecoke"
host: "localhost"
port: "3306"
user: "root"
password: ""
创建模型
pop提供一个实用工具soda。用soda可以创建模型。
$ soda generate model user title:string first_name:string last_name:string bio:text -e development
v3.41.1
--> models/user.go
--> models/user_test.go
--> goimports -w models/user.go models/user_test.go
> migrations/20171218173819_create_users.up.fizz
> migrations/20171218173819_create_users.down.fizz
soda创建了两个文件夹:models和migrations。用户模型存储在其中models/user.go,初始迁移存储在migrations/20171218173819_create_users.up.fizz。fizz下面会讲到如何使用。
创建数据
-e development 代表创建开发环境下的数据库,当然也可以是test和production。
$ soda create -e development
完成fizz
编辑 migrations/20171218173819_create_users.up.fizz文件
create_table("users") {
t.Column("id", "uuid", {primary: true})
t.Timestamps()
t.Column("name", "string", {})
t.Column("email", "string", {})
t.Column("password_hash", "string", {"size":64})
t.Column("register_time", "timestamp", {"default": null})
t.Column("last_login_time", "timestamp", {"default": null})
}
add_index("users", "name", {"unique": true})
add_index("users", "email", {"unique": true})
运行迁移
完成了迁移的fizz文件,就可以执行迁移
soda migrate up -e development
这样,我们的数据库,数据表都已经创建完成了。
修改表结构
项目执行过程中,由于这样那样的原因,难免表结构会改变。比如我们需要给用户表填一个location字段
soda generate fizz user_location_column
会生成一个20171219202712_user_add_location_column.up.fizz文件。
add_column("user", "location", "string", {"size": 100, "default": "New York, NY"})
为了恢复版本变化,我们需要修改20171219202712_user_add_location_column.down.fizz文件。
drop_column("user", "location")
现在您需要更新实际模型
type User struct {
ID uuid.UUID `json:"id" db:"id"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
Name string `json:"name" db:"name"`
Email string `json:"email" db:"email"`
PasswordHash string `json:"password_hash" db:"password_hash"`
Password string `json:"-" db:"-"`
PasswordConfirmation string `json:"-" db:"-"`
Location string `json:"location" db:"location"` // 这行是新增的
}
再次运行迁移
$ soda migrate up -e development
表结构修改完成,
连接数据库
tx, err := pop.Connect("development")
if err != nil {
log.Panic(err)
}
创建新纪录
jessica := models.User{
Title: "Ms.",
FirstName: "Jessica",
LastName: "Jones",
Bio: "Private security, super hero.",
}
_, err = tx.ValidateAndSave(&jessica)
if err != nil {
log.Panic(err)
}
按ID查询一条记录
id := "240ec3c5-019d-4031-9c27-8a553e022297" // frank
frank := models.User{}
err = tx.Find(&frank, id)
if err != nil {
fmt.Print("ERROR!\n")
fmt.Printf("%v\n", err)
} else {
fmt.Print("Success!\n")
fmt.Printf("%v\n", frank)
}
查询所有记录
users := []models.User{}
err = tx.All(&users)
if err != nil {
fmt.Print("ERROR!\n")
fmt.Printf("%v\n", err)
} else {
fmt.Print("Success!\n")
fmt.Printf("%v\n", users)
}
查询某些数据
query := tx.Where("last_name = 'Rand' OR last_name = 'Murdock'")
users := []models.User{}
err = query.All(&users)
if err != nil {
fmt.Print("ERROR!\n")
fmt.Printf("%v\n", err)
} else {
fmt.Print("Success!\n")
fmt.Printf("%v\n", users)
}
更新单个记录
query := tx.Where("title = 'Ms.'")
users := []models.User{}
err = query.All(&users)
if err != nil {
fmt.Print("ERROR!\n")
fmt.Printf("%v\n", err)
} else {
for i := 0; i < len(users); i++ {
user := users[i]
user.Title = "Mrs."
tx.ValidateAndSave(&user)
fmt.Print("Success!\n")
fmt.Printf("%v\n", user)
}
}
更新多个记录
更新多个记录与更新单个记录非常相似
users := []models.User{}
err = tx.All(&users)
if err != nil {
fmt.Print("ERROR!\n")
fmt.Printf("%v\n", err)
} else {
for i := 0; i < len(users); i++ {
user := users[i]
user.Location = "NYC, NY"
tx.ValidateAndSave(&user)
fmt.Print("Success!\n")
fmt.Printf("%v\n", user)
}
}
删除单个记录
id := "240ec3c5-019d-4031-9c27-8a553e022297"
frank := models.User{}
err = tx.Find(&frank, id)
if err != nil {
fmt.Print("ERROR!\n")
fmt.Printf("%v\n", err)
} else {
fmt.Print("Success! - Now delete it.\n")
tx.Destroy(&frank)
}
删除多条记录
删除多条记录与删除单条记录非常相似,不列出来了。
我以为生成模型是根据现有数据表生成
结果生成个默认的
当然大部分的orm工具都是具备这个功能的,但是我一般不这么用。因为:
1.应用设计的时候就不应该数据库强依赖。
2.反向的时候,一般来说有些细节处理的不是太好,还需要手动调整。
3.利用迁移工具还可以看出来数据库版本的历史。