Database/sql 及 GORM 相关解读 | 青训营笔记

89 阅读3分钟

这是我参与【第五届青训营】伴学笔记创作活动的第5天

一、本堂课重点内容

  • 1、理解database/sql
    • 基本用法
    • 设计原理
    • 基础概念
  • 2、GORM使用简介
    • 基本用法
    • Model定义
    • 惯例约定
    • 关联介绍

二、详细知识点介绍

1、理解database/sql

(1)基本用法

【数据库连接】

import driver实现,使用driver+DSN初始化DB连接

import _"github.com/go-sql-driver/mysql"

func main(){
    db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/hello")
}

【单条sql语句】

执行一条SQL,通过rows取回返回的数据,处理完毕,需要释放连接

rows, err := db.Query("select id,name from users where id = ?", 1)
if err != nil {
    // ...
}
defer rows.Close()

【数据、错误处理】

var users []User
for rows.Next(){
    var user User
    err := rows.Scan(&user.ID, &user.Name)
    
    if err != nil{
        // ...
    }
    users = append(users, user)
}


if rows.Err() != nil{
    // ...
}

(2)设计原理

image.png

【连接池】

image.png

【Driver连接接口】

image.png

image.png

image.png

2、GORM使用简介

(1)基本用法 - CRUD

1、操作数据库

db.AutoMigrate(&Product{})

db.Migrator().CreateTable(&Product{})

2、创建

user := User{Name:"Jinzhu", Age:18, Birthday:time.Now()}
result := db.Create(&user)

user.ID         
result.Error         // 返回error
result.RowsAffected  // 返回影响的行数

3、批量创建

var users = []User{{Name: "jinzhu1"},{Name:"jinzhu2"},{Name:"jinzhu3"}}
db.Create(&users)
db.CreateInBatches(users, 100)

for _, user := range users{
        user.ID    // 1,2,3
}

4、读取

var product Product
db.First(&product, 1)          // 查询id为1的product
db.First(&product,"code=?","L1212")   

result := db.Find(&users, []int{1,2,3})
result.RowsAffected   // 返回找到的记录数
errors.Is(result.Error, gorm.ErrRecordNotFound)  // First,Last,Take 查不到数据

5、更新某个字段

db.Model(&product).Update("Price":2000)
db.Model(&product).UpdateColumn("Price":2000)

6、更新多个字段

db.Model(&product).Updates(Product{Price:2000, Code:"L1212"})
db.Model(&product).Updates(map[string]interface{}{"Price":2000, "Code":"L1212"})

7、批量更新

db.Model(&Product{}).Where("price < ?", 2000).Updates(map[string]interface{}{"Price": 2000})

8、删除 - 删除product

db.Delete(&product)

(2)Model定义- 惯例约定

image.png

(4) 关联

image.png

CRUD

// 保存用户及其关联 (Upsert)
db.Save(&User{
    Name :"jinzhu",
    Languages: []Language{{Name: "zh-CN"},{Name:"en-US"}}
}

//关联模式
langAssociation := db.Model(&user).Association("Languages")
//查询关联
langAssociation.Find(&languages)
// 将汉语,英语语添加到用户掌握的语言中
langAssociation.Append([]LanguageflanguageZH,languageEN3)
// 把用户掌握的语言替换为汉语,德语
langAssociation.Replace([]LanguageflanguageZH,languageDE})
//删除用户掌握的两个语言
langAssociation.Delete(languageZH,languageEN)
//删除用户所有掌握的语言
langAssociation.Clear()
// 返回用户所掌握的语言的数量
LangAssociation.Count()
// 批量模式 Append,Replace
var users = 国Userfuser1,user2,user3}
langAssociation := db.Model(&users).Association("Languages")
// 批量模式 Append,Replace,参数需要与源数据长度相同
//例如:我们有 3个user:将 userA 添加到 user1 的 Team
//将 userB 添加到 user2 的 Team,将 userA、userB、userC 添加到 user3 的 Team
db.Model(&users).Association("Team").Append(&userA, &userB,&[]User{userA, userB, userC})

Preload/Joins预加载

type User struct {
    Orders  []Order
    Profile Profile
}

// 查询用户的时候并找出其订单,个人信息 (1+1 条SQL)
db.Preload("Orders").Preload("Profile").Find(&users)
// SELECT *FROM users;
// SELECT*FROM orders WHERE user_id IN (1,2,3,4);// 一对多/
/ SELECT* FROM profiles WHERE user_id IN (1,2,3,4); // 一对-

// 使用 Join SQL 加载 (单条 JOIN SQL)
db.Joins("Company").Joins("Manager").First(&user,1)
db.Joins("Company",DB .Where(&Company[Alive: true])).Find(&users)

//预加载全部关联 (只加载一级关联)
db.Preload(clause.Associations).Find(&users)

//多级预加载
db.Preload("Orders.0rderItems.Product").Find(&users)
//多级预加载 +预加载全部一级关联db.Preload("Orders.0rderItems.Product").Preload(clause.Associations).Find(&users)

// 查询用户的时候找出其未取消的订单
db.Preloadc("Orders" ,"state NOT IN (?)","cancelled").Find(&users)
db.Preload("Orders", "state = ?", "paid").Preload("Orders.OrderItems").Find(&users)

db.Preload("Orders", func(db *gorm.DB)*gorm.DB {
    return db .Order("orders amount DESC")
 }).Find(&users)

级联删除

//方法1:使用数据库约束自动删除
type User struct{
    ID           uint
    Name         string
    Account      Account       `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
    CreditCards  []CreditCard  `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
    Orders       []Order       `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}
//需要使用 GORMMigrate 数据库迁移数据库外键才行
db.AutoMigrate(&User{})
//如果未启用软删除,在删除 User 时会自动删除其依赖
db.Delete(&User{})

// 方法2:使用 Select 实现级联删除,不依赖数据库约束及软删除
//删除 user 时,也删除 user 的 account
db.Select("Account").Delete(&user)

/删除 user 时,也删除 user 的 Orders、CreditCards 记录
db.Select("Orders","CreditCards").Delete(&user)

//删除 user 时,也删除 user 的 Orders、CreditCards 记录,也删除订单的 BillingAddress
db.Select("Orders","Orders.BillingAddress","CreditCards").Delete(&user)

//删除 user 时,也删除用户及其依赖的所有 has one/many、many2many 记录
db.Select(clause.Associations).Delete (&user)

三、课后个人总结

之前学过sql的话,这个学起来接受也快。

四、课程链接学习

Database/sql 及 GORM 相关解读 - 掘金 (juejin.cn)