从零开始Go语言Ⅵ-框架P1 | 青训营笔记

94 阅读3分钟

这是我参与「第五届青训营」伴学笔记创作活动的第6天

前言
Go框架三件套第一部分。

Gorm

概述

Gorm是Golang语言中一款性能极好的ORM库,对开发人员相对是比较友好的。(ORM:Object-Relationl Mapping,即对象关系映射。)

上手

# 使用docker快速创建一个本地可连接的mysql实例
$ docker run -itd -e MYSQL_ROOT_PASSWORD='bgbiao.top' --name go-orm-mysql  -p 13306:3306 mysql:5.6

# 登陆mysql并创建一个测试库
$ docker exec -it go-orm-mysql mysql -uroot -pbgbiao.top
....
mysql> create database test_api;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test_api           |
+--------------------+
4 rows in set (0.00 sec)

# 运行一个简单示例
$ cat gorm-mysql-example.go
package main
import (
    "fmt"
    "time"

    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)


// 定义一个数据模型(user表)
// 列名是字段名的蛇形小写(PassWd->pass_word)
type User struct {
    Id          uint        `gorm:"AUTO_INCREMENT"`
    Name        string      `gorm:"size:50"`
    Age         int         `gorm:"size:3"`
    Birthday    *time.Time
    Email       string      `gorm:"type:varchar(50);unique_index"`
    PassWord    string      `gorm:"type:varchar(25)"`
}

var db *gorm.DB

func main() {
    db,err := gorm.Open("mysql","root:bgbiao.top@(127.0.0.1:13306)/test_api?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        fmt.Errorf("创建数据库连接失败:%v",err)

    }

    defer db.Close()

    // 自动迁移数据结构(table schema)
    // 注意:在gorm中,默认的表名都是结构体名称的复数形式,比如User结构体默认创建的表为users
    // db.SingularTable(true) 可以取消表名的复数形式,使得表名和结构体名称一致
    db.AutoMigrate(&User{})


    // 添加唯一索引
    db.Model(&User{}).AddUniqueIndex("name_email", "id", "name","email")

    // 插入记录
    db.Create(&User{Name:"bgbiao",Age:18,Email:"bgbiao@bgbiao.top"})
    db.Create(&User{Name:"xxb",Age:18,Email:"xxb@bgbiao.top"})

    var user User
    var users []User
    // 查看插入后的全部元素
    fmt.Printf("插入后元素:\n")
    db.Find(&users)
    fmt.Println(users)

    // 查询一条记录
    db.First(&user,"name = ?","bgbiao")
    fmt.Println("查看查询记录:",user)

    // 更新记录(基于查出来的数据进行更新)
    db.Model(&user).Update("name","biaoge")
    fmt.Println("更新后的记录:",user)

    // 删除记录
    db.Delete(&user)

    // 查看全部记录
    fmt.Println("查看全部记录:")

    db.Find(&users)
    fmt.Println(users)
}

# 运行gorm实例
$ go run gorm-mysql-example.go
插入后元素:
[{1 bgbiao 18 <nil> bgbiao@bgbiao.top } {2 xxb 18 <nil> xxb@bgbiao.top }]
查看查询记录: {1 bgbiao 18 <nil> bgbiao@bgbiao.top }
更新后的记录: {1 biaoge 18 <nil> bgbiao@bgbiao.top }
查看全部记录:
[{2 xxb 18 <nil> xxb@bgbiao.top }]

GORM的基本使用

增、删、改表结构

// 使用模型创建
db.CreateTable(&User{})

// 增加参数创建
db.Set("gorm:table_options", "ENGINE=InnoDB").CreateTable(&User{})

// 删除表
db.DropTable(&User{})
db.DropTable("users")

// 模型和表名的混搭
db.DropTableIfExists(&User{}, "products")


// 修改列(修改字段类型)
db.Model(&User{}).ModifyColumn("description", "text")

// 删除列
db.Model(&User{}).DropColumn("description")

// 指定表名创建表
db.Table("deleted_users").CreateTable(&User{})

// 指定表名查询
var deleted_users []User
db.Table("deleted_users").Find(&deleted_users)

创建

插入记录

// 相当于insert into users(name,age,brithday) values("BGBiao",18,time.Now())
user := User{Name: "BGBiao", Age: 18, Birthday: time.Now()}
// 主键为空返回`true`
db.NewRecord(user)
db.Create(&user)
// 创建`user`后返回`false`
db.NewRecord(user)

查询

基本查询

// 根据主键查询第一条记录
// SELECT * FROM users ORDER BY id LIMIT 1;
db.First(&user)


// 随机获取一条记录
// SELECT * FROM users LIMIT 1;
db.Take(&user)


// 根据主键查询最后一条记录
// SELECT * FROM users ORDER BY id DESC LIMIT 1;
db.Last(&user)


// 查询所有的记录
// SELECT * FROM users;
db.Find(&users)


// 查询指定的某条记录(仅当主键为整型时可用)
// SELECT * FROM users WHERE id = 10;
db.First(&user, 10)

结构体方式查询

// 结构体方式
// select * from users where name = 'bgbiao.top'
db.Where(&User{Name: "bgbiao.top", Age: 20}).First(&user)

// Map方式
// select * from users where name = 'bgbiao.top' and age = 20;
db.Where(map[string]interface{}{"name": "bgbiao.top", "age": 20}).Find(&users)

// 主键的切片
// select * from users where id in (20,21,22);
db.Where([]int64{20, 21, 22}).Find(&users)

更新

更新所有字段

注意:save会更新所有字段,及时没有赋值

db.First(&user)

user.Name = "bgbiao.top"
user.Age = 100
// update users set name = 'bgbiao.top',age=100 where id = user.id
db.Save(&user)

更新修改字段

使用UpdateUpdates方法

// 更新单个属性,如果它有变化
// update users set name = 'hello' where id = user.id
db.Model(&user).Update("name", "hello")

// 根据给定的条件更新单个属性
// update users set name = 'hello' where active = true
db.Model(&user).Where("active = ?", true).Update("name", "hello")

// 使用 map 更新多个属性,只会更新其中有变化的属性
// update users set name = 'hello',age=18,actived=false where id = user.id
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})

// 使用 struct 更新多个属性,只会更新其中有变化且为非零值的字段
db.Model(&user).Updates(User{Name: "hello", Age: 18})

// 警告:当使用 struct 更新时,GORM只会更新那些非零值的字段
// 对于下面的操作,不会发生任何更新,"", 0, false 都是其类型的零值
db.Model(&user).Updates(User{Name: "", Age: 0, Actived: false})

更新选定字段

如果想要更新或者忽略某些字段,可以先使用SelectOmit

// update users set name = 'hello' where id = user.id;
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})

// Omit()方法用来忽略字段
// update users set age=18,actived=false where id = user.id
db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})

SQL表达式更新

// update products set price = price*2+100 where id = product.id
DB.Model(&product).Update("price", gorm.Expr("price * ? + ?", 2, 100))

// update products set price = price*2+100 where id = product.id;
DB.Model(&product).Updates(map[string]interface{}{"price": gorm.Expr("price * ? + ?", 2, 100)})

// update products set quantity = quantity-1 where id = product.id;
DB.Model(&product).UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))

// update products set quantity = quantity -1 where id = product.id and quantity > 1
DB.Model(&product).Where("quantity > 1").UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))

删除

删除记录

注意: 删除记录时,请确保主键字段有值,GORM 会通过主键去删除记录,如果主键为空,GORM 会删除该 model 的所有记录。

// 删除现有记录
// delete from emails where id = email.id;
db.Delete(&email)

// 为删除 SQL 添加额外的 SQL 操作
// delete from emails where id = email.id OPTION (OPTIMIZE FOR UNKNOWN)
db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email)

待整理后持续更新