Go语言上手(六)-Gorm上手| 青训营笔记

108 阅读3分钟

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

  • Gorm框架
  • Go的sql设计与思路
  • 字节内部的框架

课堂感受:

这节课堂非常的偏向实战方面,非常的面向开发

Gorm

数据表-结构体

数据行-结构体实例

字段-结构体字段

官方文档

GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.

前言

SQL语句及其种类

DDL(Data Definition Language,数据定义语言) 用来创建或者删除存储数据用的数据库以及数据库中的表等对象

DML(Data Manipulation Language,数据操纵语言) 用来查询或者变更表中的记录。

DCL(Data Control Language,数据控制语言) 用来确认或者取消对数据库中的数据进行的变更。除此之外,还可以对 RDBMS 的用户是否有权限操作数据库中的对象(数据库表等)进行设定

安装

go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite

连接数据库

dsn := "root:zhang134679@tcp(127.0.0.1:3306)/tiktok?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

原生连接数据库

image-20230119185939926

模型定义

type User struct {
  ID           uint
  Name         string
  Email        *string
  Age          uint8
  Birthday     *time.Time
  MemberNumber sql.NullString
  ActivatedAt  sql.NullTime
  CreatedAt    time.Time
  UpdatedAt    time.Time
}

GORM 倾向于约定优于配置 默认情况下,GORM 默认使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAtUpdatedAt 字段追踪创建、更新时间

自定义

// 定义模型
type Animal struct {
   AnimalID int64 `gorm:"primary_key"`
   Name     string
   Age      int
}
CREATE TABLE `animals` (
  `animal_id` bigint NOT NULL AUTO_INCREMENT,
  `name` longtext,
  `age` bigint DEFAULT NULL,
  PRIMARY KEY (`animal_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

约定大于配置

表名为struct name的snake_case的复数格式

字段名为filed name 的snanke_case的单数格式

Id/id字段为主键,如果为数字,则为自增主键

createdAt字段,创建时候,保存当前时间

UpdatedAt字段,创建,更新的时候保存当前时间

gorm.DeletedAt 字段,默认开启soft delete模式 默认为空 删除则为时间戳

gorm会把为空的值的字段不插入数据库

也就是:所有字段的零值,比如0,“”,false或者其他的零值,都不会保存再数据库中,但是会使用他们的默认值

想要避免这种情况,使用指针或者Scaner接口

curd

package main
​
import (
   "fmt"
   "gorm.io/driver/mysql"
   "gorm.io/gorm"
)
​
type User struct {
   ID    uint
   Name  string
   Email string
   Age   uint8
}
​
func main() {
   // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
   dsn := "root:zhang134679@tcp(127.0.0.1:3306)/tiktok?charset=utf8mb4&parseTime=True&loc=Local"
   db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
   if err != nil {
      panic(err)
   }
   //创建表 自动迁移
   db.AutoMigrate(&User{})
   //创建数据行
   //user := User{
   // 0,
   // "bowen",
   // "WenTesla@163.com",
   // 22,
   //}
   //db.Create(&user)
   //查询数据行
   var u User
   db.First(&u)
   fmt.Println("查询到:", u)
   //更新数据库
   db.Model(&u).Update("Name", "bowenzhang")
   //删除
   db.Delete(&u)
   
}

//Read

Frist(&product,1) //根据主键查找

First(&product,"code = ?","xxx") //查找code字段值为xxx的记录

//Update

db.model(&product).update("Price",200)

// 更新多个字段

db.Model(&product).Updates(Product{Price:200,Code:"Fxxx"})

默认使用蛇形

upsert

使用clause.OnCinflict处理数据冲突

// 已不解决冲突为例子,创建一个数据
p:=&Product{Code:"D42",ID:1}
db.Clauses(class.OnConfict{DoNothing:true}).Create(&p)

AutoMigrate线上环境禁止使用

自动迁移数据库可能会导致数据库变化

关联模式

image-20230119191510373

预加载

image-20230119191623743

for update 的作用和目的: select for update 是为了在查询时,对这条数据进行加锁,避免其他用户以该表进行插入,修改或删除等操作,造成表的不一致性.

原始sql

select `name`,`age`,`employee_number` from `users` where 
role <> "manager" AND
age >35
order by age DESC
limit 10 offset 10
for update

grom

db.where("role <> ?","manager").Where("age > ?",35).limit(100).Order("age Desc").Find(&user)

image-20230119192629891

connpool

欲缓冲

image-20230119211344187

字节实战

创建sql表达式

image-20230119212530179

有三种方法

方法三可以自定义接口

批量数据操作-创建

image-20230119212923563

使用事务

  • Begin() 开启
  • RollBack()回滚
  • Commit()提交

注意要使用tx使用事务

tx:=db.Begin() //开启事务

image-20230120110417236

个人思考: 字节的项目先分了层:如下所示

image.png

收获:
由于没有linux环境,window上的wsl配置不够,window上文件太多,没有条件开启wsl,所以这个字节的这个框架就没有使用,但是,Gorm的收获很多,踩坑的Api也很多,非常感谢课程的播出