这是我参与「第五届青训营 」伴学笔记创作活动的第 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{})
原生连接数据库
模型定义
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 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间
自定义
// 定义模型
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线上环境禁止使用
自动迁移数据库可能会导致数据库变化
关联模式
预加载
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)
connpool
欲缓冲
字节实战
创建sql表达式
有三种方法
方法三可以自定义接口
批量数据操作-创建
使用事务
- Begin() 开启
- RollBack()回滚
- Commit()提交
注意要使用tx使用事务
tx:=db.Begin() //开启事务
个人思考: 字节的项目先分了层:如下所示
收获:
由于没有linux环境,window上的wsl配置不够,window上文件太多,没有条件开启wsl,所以这个字节的这个框架就没有使用,但是,Gorm的收获很多,踩坑的Api也很多,非常感谢课程的播出