GO的数据库操作(GORM)

数据库连接

这边主要是使用记录mysq数据库的操作,这边使用gorm是v2.0,所以注意扩展的引入地址

  • 首先引入扩展包
import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)
  • 连接数据
dsn := "用户名:密码@tcp(IP地址:3306)/tar?charset=utf8mb4&parseTime=True&loc=Local"
dbconn, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
	panic(err)//打印错误
}

数据库的查询

1.首先定义2个结构体,1个是对应数据库表的需要引入gorm.Model,一个是用来存储查询结果的

2.然后对应手册看需要用到的对应函数方法

简单示例:获取表中全部数据并返回json格式数据

//供应商类型结构体定义
type (
	Supplier struct {
		gorm.Model
		ID           uint   `json:"id"`
		SupplierName string   `json:"supplier_name"`
		SourceName  string   `json:"source_name"`
		DockingName       string      `json:"docking_name"`
		Tel     string   `json:"tel"`
		CompanyProfile string `json:"company_profile"`
	}
	TransformedSupplier struct {
		ID           uint   `json:"id"`
		SupplierName string   `json:"supplier_name"`
		SourceName  string   `json:"source_name"`
		DockingName       string      `json:"docking_name"`
		Tel     string   `json:"tel"`
		CompanyProfile string `json:"company_profile"`
	}
)
//自定义表名称,数据库操作时给结构体指定对应的表名
func (Supplier) TableName() string {
	return "qc_suppliers"
}
//连接数据库
dsn := "用户名:密码@tcp(IP地址:3306)/tar?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
	panic(err)//打印错误
}
//定义存储查询结果的变量
var result []*TransformedSupplier
//指定查询model(对应的数据结构体名称),FIND(存储查询结果的变量地址)
db.Model(&Supplier{}).Find(&result)
//返回json格式数据
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": result})

相关其他查询函数的应用

  • db.First(&user)// 获取第一条记录(主键升序) db.First(&user)
  • db.Take(&user)// 获取一条记录,没有指定排序字段
  • db.Model(&User{}).First(&result) // SELECT * FROM users ORDER BY users.id LIMIT 1
  • db.Find(&users, []int{1,2,3}) // SELECT * FROM users WHERE id IN (1,2,3);
  • db.First(&user, “10”) // SELECT * FROM users WHERE id = 10;
  • db.Where(“name = ? AND age >= ?”, “jinzhu”, “22”).Find(&users)// SELECT * FROM users WHERE name = ‘jinzhu’ AND age >= 22;
  • db.Where(“role = ?”, “admin”).Or(“role = ?”, “super_admin”).Find(&users)// SELECT * FROM users WHERE role = ‘admin’ OR role = ‘super_admin’;
  • db.Select(“name”, “age”).Find(&users) // SELECT name, age FROM users;
  • db.Order(“age desc, name”).Find(&users) // SELECT * FROM users ORDER BY age desc, name;
  • db.Limit(10).Offset(5).Find(&users) // SELECT * FROM users OFFSET 5 LIMIT 10;
  • db.Model(&User{}).Select(“name, sum(age) as total”).Group(“name”).Having(“name = ?”, “group”).Find(&result) // SELECT name, sum(age) as total FROM users GROUP BY name HAVING name = “group”

相关常用函数,自己随意整理

函数名称

大概含义

First(&user)

获取根据主键升序得第一条记录

Take(&user)

获取一条记录,没有指定排序字段

Last(&user)

获取最后一条记录(主键降序)

Model(&User{})

指定表名Model(&结构体)

Find(&users)

// 获取全部记录result.RowsAffected // 返回找到的记录数,相当于 len(users) result.Error // returns error

Where(“name = ?”, “jinzhu”)

Where(“条件语句”,问号标识得具体值)

Where(&User{Name: “jinzhu”, Age: 20}).

也可以用结构体

db.Find(&user, “name = ?”, “jinzhu”)

也可以和where相似用法

db.Find(&users)

直接写不带参,获取全部

Where().Or().

左右2边写2条件,例如Where(“role = ?”, “admin”).Or(“role = ?”, “super_admin”)

Select(“字段一”, “字段2”).

Select(“name”, “age”)读取指定字段

Order(“排序条件”)

Order(“age desc, name”)//指定排序条件

Limit(10).Offset(5)

Limit(每页数量),Offset(起始位置)

Group(指定分组字段)

.Group(“date(created_at)”)

Having(分组条件).

Having(“sum(amount) > ?”, 100).

Table(“orders”)

直接指定操作数据库表名

Distinct(“name”, “age”).

去重

Joins(关联条件)

db.Model(&User{}).Select(“users.name, emails.email”).Joins(“left join emails on emails.user_id = users.id”).Scan(&result{})

Scan(结构体)

Scan 结果至 struct,用法与 Find 类似

新增数据

Create函数,引入结构体指针,单个插入

supplier := Supplier{SupplierName: "Jinzhu", SourceName: "测试", DockingName: "YW"}
result := db.Create(&supplier) // 通过数据的指针来创建

//user.ID  返回插入数据的主键
//result.Error   返回 error
//result.RowsAffected 返回插入记录的条数

批量插入操作

var suppliers = []Supplier{{SupplierName: "jinzhu1"}, {SupplierName: "jinzhu2"}, {SupplierName: "jinzhu3"}}
db.Create(&suppliers)

for _, user := range users {
  user.ID // 1,2,3  生成得自增id
}

指定插入数量

var 用户 = []Supplier{SupplierName: "jinzhu_1"}, ...., {SupplierName: "jinzhu_10000"}}

// 数量为 100
db.CreateInBatches(用户, 100)

还可以根据map创建

db.Model(&Supplier{}).Create(map[string]interface{}{
  "Name": "jinzhu", "Age": 18,
})

// batch insert from `[]map[string]interface{}{}`
db.Model(&Supplier{}).Create([]map[string]interface{}{
  {"SupplierName": "jinzhu_1"},
  {"SupplierName": "jinzhu_2"},
})

数据更新

更新指定字段数据

db.First(&user)

Supplier.SupplierName = "jinzhu 2"
Supplier.SourceName = "gg 2"
db.Save(&Supplier)

指定条件更新

// 条件更新
db.Model(&Supplier{}).Where("score = ?", 10).Update("supplier_name", "hello")
// UPDATE supplier SET supplier_name='hello', updated_at='2022-05-09 21:34:10' WHERE score=10;

// 根据 `struct` 更新属性,只会更新非零值的字段
db.Model(&Supplier).Where("id = ?", 111).Updates(Supplier{SupplierName: "hello", SourceName: "boss"})
// UPDATE users SET supplier_name='hello', score=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;

批量更新

// 通过 `RowsAffected` 得到更新的记录数
result := db.Model(Supplier{}).Where("role = ?", "admin").Updates(Supplier{SupplierName: "hello", SourceName:  "boss"})
// UPDATE users SET  score=18 WHERE supplier_name = 'admin;
result.RowsAffected // 更新的记录数
result.Error        // 更新的错误

删除数据

删除指定数据

// 带额外条件的删除
db.Where("supplier_name = ?", "jinzhu").Delete(&email)
// DELETE from supplier where id = 10 AND supplier_name = "jinzhu";
db.Delete(&User{}, 10)
// DELETE FROM supplier WHERE id = 10;

db.Delete(&Supplier{}, "10")
// DELETE FROM supplier WHERE id = 10;

db.Delete(&Supplier, []int{1,2,3})
// DELETE FROM supplier WHERE id IN (1,2,3);

软删除

如果您的模型包含了一个 gorm.deletedat 字段(gorm.Model 已经包含了该字段),它将自动获得软删除的能力!

拥有软删除能力的模型调用 Delete 时,记录不会被从数据库中真正删除。但 GORM 会将 DeletedAt 置为当前时间, 并且你不能再通过正常的查询方法找到该记录。

// user 的 ID 是 `111`
db.Delete(&Supplier)
// UPDATE supplier SET deleted_at="2022-04-29 10:23" WHERE id = 111;

// 批量删除
db.Where("age = ?", 20).Delete(&Supplier{})
// UPDATE supplier SET deleted_at="2022-04-29 10:23" WHERE score = 20;

// 在查询时会忽略被软删除的记录
db.Where("age = 20").Find(&Supplier)
// SELECT * FROM supplier WHERE score = 20 AND deleted_at IS NULL;

查看软删除和永久的删除

db.Unscoped().Where("score = 20").Find(&Supplier)
// SELECT * FROM supplier WHERE score = 20;
db.Unscoped().Delete(&Supplier)
// DELETE FROM supplier WHERE id=10;