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)
    }

删除多条记录

删除多条记录与删除单条记录非常相似,不列出来了。

superwen
讨论数量: 2

我以为生成模型是根据现有数据表生成
结果生成个默认的

4年前 评论
superwen

当然大部分的orm工具都是具备这个功能的,但是我一般不这么用。因为:

1.应用设计的时候就不应该数据库强依赖。
2.反向的时候,一般来说有些细节处理的不是太好,还需要手动调整。
3.利用迁移工具还可以看出来数据库版本的历史。

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!