Gorm 基础
Gorm 快速入门
GORM github地址: https://github.com/go-gorm/gorm GORM 官网地址: https://gorm.io/zh_CN/docs/
主操作: MYSQL
安装
//安装MySQL驱动、gorm包
go get -u gorm.io/driver/mysql
go get -u gorm.io/gorm增删改查
package main
import (
"errors"
"fmt"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
gorm.Model // gorm 自带模型继承
Username string `gorm:"column:username;not null"` // 列名(字段名)为username,不为空
Password string `gorm:"column:password;not null"`
}
// 设置表名,可以通过给struct类型定义 TableName函数,返回当前struct绑定的mysql表名是什么
func (u User) TableName() string {
return "users"
}
func main() {
//配置MySQL连接参数
username := "root" //账号
password := "123456" //密码
host := "127.0.0.1" //数据库地址,可以是Ip或者域名
port := 3306 //数据库端口
Dbname := "tizi365" //数据库名
/*
通过前面的数据库参数,拼接 MYSQL DSN, 其实就是数据库连接串(数据源名称)
MYSQL dsn格式: {username}:{password}@tcp({host}:{port})/{Dbname}?charset=utf8&parseTime=True&loc=Local
*/
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", username, password, host, port, Dbname)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("连接数据库失败, error=" + err.Error())
}
// 自动创建表 users, 也就是上面模型 User
db.AutoMigrate(&User{})
/* 增 */
u := User{
Username: "tizi365",
Password: "123456",
}
// 错误处理,默认gorm.DB的Error属性为 nil, 检测 Error 是否为nil
if err := db.Create(&u).Error; err != nil {
fmt.Println("插入失败", err)
return
}
/* 查 */
u = User{}
result := db.Where("username = ?", "tizi365").First(&u)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
fmt.Println("找不到记录")
return
}
fmt.Println(u.Username, u.Password)
/* 改 */
db.Model(&User{}).Where("username = ?", "tizi365").Update("password", "654321")
/* 删 */
db.Where("username = ?", "tizi365").Delete(&User{})
}GORM 调试模式
会打印执行的 sql 语句
GORM 高并发
提高数据库连接的使用率,避免重复建立数据库连接带来的性能消耗,会经常使用数据库连接池技术来维护数据库连接。
1、定义tools包,负责数据库初始化工作
使用例子
GORM 插入数据
GORM 查询数据
Take
查询一条数据
First
查询一条记录,根据主键ID排序(正序),返回第一条记录
Last
查询一条记录, 根据主键ID排序(倒序),返回第一条记录
Find
查询多条记录,Find函数返回的是一个数组
Pluck
查询一列值
where
语法:db.Where(query interface{}, args ...interface{})
select
设置select子句, 指定返回的字段
order
设置排序语句,order by子句
limit & Offset
设置limit和Offset子句,分页的时候常用语句。
count
Count函数,直接返回查询匹配的行数。
group by
直接执行sql语句
对于复杂的查询,例如多表连接查询,我们可以直接编写sql语句,然后执行sql语句。 gorm通过db.Raw设置sql语句,通过Scan执行查询。
GORM 更新数据
通过结构体变量更新字段值, gorm库会忽略零值字段。就是字段值等于0, nil, "", false这些值会被忽略掉,不会更新。如果想更新零值,可以使用map类型替代结构体。
Save
相当于根据主键id,更新所有模型字段值。
Update
更新单个字段值
自定义条件更新记录
更新某个 id 的多个记录
更新符合条件的记录
更新零值,使用 map 代替结构体去更新
计算更新表达式
UPDATE foods SET stock = stock + 1 WHERE id = '2'
这样的带计算表达式的更新语句gorm怎么写?
gorm提供了Expr函数用于设置表达式
GORM 删除数据
删除单条数据
删除符合条件数据
GORM事务处理
自动事务
通过db.Transaction函数实现事务,如果闭包函数返回错误,则回滚事务。
手动事务
在开发中经常需要数据库事务来保证多个数据库写操作的原子性。例如电商系统中的扣减库存和保存订单。
共用: 多表关联测试
一对多
继承共用代码
一对多测试模型
添加测试数据
查询某用户拥有几张信用卡
查询某个用户名下有几张信用卡
查询某ID的信用卡和归属用户
查询所有用户和所属信用卡
查询所有信用卡和归属用户
一对多,级联删除
删除用户,并会把此用户名下的信用卡所属 user_id 设置为空
一对一
一对一模型
用户查询自身份证
Joins 连表方式
身份证反向查询用户
多对多
举例账号和角色的关联关系; 一个账号可以有多个角色,一个角色也可以给多个账号的关联 如果查看数据库的话,会发现有三张表,多出的一张表是存储 角色和账户的关系: account_role
many2many:account_role 定义中间表名为:account_role
foreignKey:Id 使用当前表的id作为外键
joinForeignKey:accountId 当前数据模型外键关联到中间件表的字段名叫accountId
joinReferences:roleId 反向引用字段,如果是账号表就要写中间表的roleId
添加测试数据
通过用户查询角色
通过角色反查用户
参考地址
Beforce
GORM 模型定义
内置模型约定
默认情况下: GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间
例如:
自定义匿名字段模型约定
默认是有一个 gorm.Model, 但是我不想用,我想自定义,让所有表中都携带我自定义的字段
自定义正常字段模型约定
比如某些公共的字段,可以被其他结构体调用
column
指定 db 列名
gorm:"column:username"
type
数据类型 bool、int、uint、float、string、time、bytes
gorm:"type:int" // 设置类型为int
gorm:"type:varchar(20);not null "
size
指定列大小
gorm:"size:255" // 设置字段大小为255
primaryKey
指定列为主键
gorm:"primaryKey"
unique
指定列为唯一
gorm:"unique" // 唯一
default
指定列的默认值
gorm:"default:0" // 默认值为0
precision
指定列的精度
scale
指定列大小
not null
指定列为 NOT NULL
gorm:"not null" // 不为空
autoIncrement
指定列为自动增长
gorm:"AUTO_INCREMENT"
autoIncrementIncrement
自动步长,控制连续记录之间的间隔
embedded
嵌套字段
gorm:"embedded"
embeddedPrefix
嵌入字段的列名前缀
autoCreateTime
创建时追踪当前时间,对于 int 字段,它会追踪秒级时间戳,使用 nano/milli 来追踪纳秒、毫秒时间戳
gorm:"embedded;embeddedPrefix:xxxx_"
autoUpdateTime
创建/更新时追踪当前时间,对于 int 字段,它会追踪秒级时间戳,您可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoUpdateTime:milli
index
根据参数创建索引,多个字段使用相同的名称则创建复合索引,查看 索引 获取详情
gorm:"index"
gorm:"index:addr"// 给address字段创建名为addr的索引
uniqueIndex
与 index 相同,但创建的是唯一索引
check
创建检查约束
check:age > 13
<-
设置字段写入的权限, <-:create 只创建、<-:update 只更新、<-:false 无写入权限、<- 创建和更新权限
`gorm:"<-:create"
->
设置字段读的权限,->:false 无读权限
-
忽略该字段,- 无读写权限
gorm:"-" // 忽略本字段
comment
迁移时为字段添加注释
gorm:"column:beast_id" // 设置列名为 beast_id
表字段标签
表关联标签
foreignKey
指定当前模型的列作为连接表的外键
references
指定引用表的列名,其将被映射为连接表外键
polymorphic
指定多态类型,比如模型名
polymorphicValue
指定多态值、默认表名
many2many
指定连接表表名
joinForeignKey
指定连接表的外键列名,其将被映射到当前表
joinReferences
指定连接表的外键列名,其将被映射到引用表
constraint
关系约束,例如:OnUpdate、OnDelete
复数表名(表名)
表名是结构体名称的复数形式
GORM 数据库连接
GORM 官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server
官方通往: https://gorm.io/zh_CN/docs/connecting_to_the_database.html
或者参考: 惯例 - 人人学go惯例 - 人人学go
MYSQL 官方指南配置
mysql.Config的源码
gorm调试模式
MYSQL 单机测试使用
示例一
MYSQL 封装测试调用
main
tools/tools.go 封装 mysql (测试使用)
viper
安装 Viper
Viper 作用
设置默认值
读取 JSON、TOML、YAML(YML)、HCL、envfile 和 Java properties 属性配置文件
实时查看和重读配置文件(可选)
从环境变量中读取
从远程配置系统(etcd 或 Consor)读取数据,并观察变化
从命令行标志读取
从缓冲区读取
设置显式值
Viper获取值
每一个Get方法在找不到值的时候都会返回零值。为了检查给定的键是否存在,提供了IsSet()方法。
读取配置文件
写入配置文件
WriteConfig - 将当前的viper配置写入预定义的路径并覆盖(如果存在的话)。如果没有预定义的路径,则报错。
SafeWriteConfig - 将当前的viper配置写入预定义的路径。如果没有预定义的路径,则报错。如果存在,将不会覆盖当前的配置文件。
WriteConfigAs - 将当前的viper配置写入给定的文件路径。将覆盖给定的文件(如果它存在的话)。
SafeWriteConfigAs - 将当前的viper配置写入给定的文件路径。不会覆盖给定的文件(如果它存在的话)。
监控配置文件热加载
只需告诉viper实例watchConfig。可选地,你可以为Viper提供一个回调函数,以便在每次发生更改时运行。
从io.Reader读取配置
Viper预先定义了许多配置源,如文件、环境变量、标志和远程K/V存储,但你不受其约束。你还可以实现自己所需的配置源并将其提供给viper。
远程Key/Value存储示例
更多其他方法参考
https://www.liwenzhou.com/posts/Go/viper_tutorial/#autoid-1-4-0
示例读取(ini,yaml)
当前路径下有两个文件
Last updated