Gorm框架
Gorm框架
简介
- ORM(Object Relational Mapping) 对象关系映射模式
为了解决面向对象与关系型数据库存在的互不匹配现象的技 术.
简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化
到关系数据库中. - Gorm是面向golang语言的一种ORM框架,支持多种数据库的接入,如:MYSQL,PostgreSQL, SQLite, SQL server, Click house. 此框架弱化了开发者对于sql语言的掌握,使用提供的api进行底层数据库的访问.
1.连接数据库
- 简单连接
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
//
func main() {
//mysql数据库的地址: "用户名:密码@tcp(127.0.0.1:3306)/数据库名?charset=urf8mb4parseTime=True&loc=Local"
mysql_Addr := "user:pass@tcp(ip:port)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
//连接与错误处理
db, err := gorm.Open(mysql.Open(mysql_Addr), &gorm.Config{})
if err != nil {
panic("failed to connect databaese!")
}
} - 高级配置
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: mysql_Addr,
// DSN data source name
DefaultStringSize: 256,
// string 类型字段的默认长度
DisableDatetimePrecision: true,
// 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
DontSupportRenameIndex: true,
// 重命名索引时采用删除并新建的方式,
//MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
DontSupportRenameColumn: true,
// 用 `change` 重命名列,
//MySQL 8 之前的数据库和 MariaDB 不支持重命名列
SkipInitializeWithVersion: false,
// 根据当前 MySQL 版本自动配置
DriverName: "my_mysql_driver",
//数据库驱动
}), &gorm.Config{
SkipDefaultTransaction: false,
NamingStrategy: schema.NamingStrategy{
//表名前缀
TablePrefix: "gva_",
//使用单数表名
SingularTable: false,
},
//逻辑外链 (代码里面自带外键 外键关系)
DisableForeignKeyConstraintWhenMigrating: true,
}) - 连接池
数据库操作都是通过连接去执行的,频繁的创建与销毁连接,比较浪费资源,因此会采用连接池对连接进行复用
.GORM使用 database/sql维护理解成sqlDB, err := db.DB()
// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(10)
// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(100)
// SetConnMaxLifetime 设置了连接可复用的最大时间。
sqlDB.SetConnMaxLifetime(time.Hour)
2. 模型
约定
默认情况下,gorm使用ID
作为主键,使用结构体的小写复数英文为表名,字段名的小写为列名
结构体字段名首字母应该大写
关键标签gorm:"primarykey"
:主键gorm:"column:db_list_name"
:指定 db 列名gorm:"not null"
:指定列为 NOT NULLgorm:"default:默认值"
:定义列的默认值gorm:"comment:注释"
:迁移时为字段添加注释
表的创建
以结构体绑定表
*gorm.DB.AutoMigrate(&struct_Name{}) |
SQL操作(CRUD)
新增记录
Create
函数
*gorm.DB.Create(&struct_Name{"key":"value"}) |
查询记录
普通查询
- 查询需要接受返回值,接受形式有map与struct
- 查询主键排序后的第一条
First
函数 - 查询一条记录,不指定字段排序
Take
函数 - 查询最后一条记录
Last
函数
检索
在函数内增加条件
Where
函数*gorm.DB.Where("字段名1 = ? AND 字段名2 = ?", "value").First(&接收)
多条件时可以使用的函数
AND
关键字LIKE
关键字,配合使用通配符%,..Or
函数Not
函数
内联条件
//将写入where的条件写在查询函数内
*gorm.DB.First(&User4, "name = ?", "xxxx")查询多条记录
Find
函数查询特定字段
select
函数
高级查询
- 智能选择字段
- 使用新结构体进行接收数据
修改记录,更新记录
Update
函数 :只更新选择的字段Updates
函数 :更新所有字段,,此时的两种形式,map与结构体,结构体零值则不参与更新Sava
函数 :无论如何都更新,包括零值
删除记录
Delete
函数
gorm中的Delete函数是进行了软删除,删除后,会有删除记录在表内
**UnScoped()**前缀硬删除
原生SQL
4.关联
默认外键名是拥有者的类型名加上其主键字段名
一对一 (one2one)
Belong to (属于)
例:你有一个目标
belong to
:一个模型User
与另一个模型Company
建立连接.这种模型User
的每一个实例都属于另一种模型Company
的一个实例
// `User` 属于 `Company`,`CompanyID` 是外键 |
- 结构一定要正确,不然会创建失败
- (外键与结构体嵌入,外键为结构体名加ID, 结构体字段名与结构体名相同)
外键重写
对
能建立关联
的关系创建与删除关系//创建关系
*gorm.DB.Model(&User{}).Association("Company").Append(&Company_object)
//删除关系
*gorm.DB.Model(&User{}).Association("Company").Delete(&Company_object)
Has one (具有一个)
例:你有一个东西
// User 有一张 CreditCard,UserID 是外键 |
.Preload("")
,预加载函数,提前拿出结构体数据外键重写
对
能建立关联
的关系创建与删除关系//创建关系
*gorm.DB.Model(&User{}).Association("CreditCard").Append(&CreditCard_object)
//删除关系
*gorm.DB.Model(&User{}).Association("CreditCard").Delete(&CreditCard_object)
一对多
Has Many (有很多个)
例:有很多卡,并且这些卡只属于你
// User 有多张 CreditCard,UserID 是外键 |
Many to Many (多对多关系)
例:你会几门语言,但语言不不只属于你
// User 拥有并属于多种 language,`user_languages` 是连接表 |
没有标签创建不了表
gorm:"many2many:user_languages;"
user_languages
是连接表
- 为防止重复创建,应自己添加主键信息
关联模式 (One2One内有例子)
开始关联模式
var user User
db.Model(&user).Association("Languages")
db.Model(&user).Association("Languages").Erroruser
是关系主体模型,它的主键不能为空- 关系的字段名是
Languages
- 如果匹配了上面两个要求,会开始关联模式,否则会返回错误
查找关联: 查找所有匹配的关联记录
db.Model(&user).Association("Languages").Find(&languages)
//查找带条件的关联
codes := []string{"zh-CN", "en-US", "ja-JP"}
db.Model(&user).Where("code IN ?", codes).Association("Languages").Find(&languages)
db.Model(&user).Where("code IN ?", codes).Order("code desc").Association("Languages").Find(&languages)添加关联
为 many to many、has many 添加新的关联;为 has one, belongs to 替换当前的关联db.Model(&user).Association("Languages").Append([]Language{languageZH, languageEN})
db.Model(&user).Association("Languages").Append(&Language{Name: "DE"})
db.Model(&user).Association("CreditCard").Append(&CreditCard{Number: "411111111111"})替换关联
用一个新的关联替换当前的关联db.Model(&user).Association("Languages").Replace([]Language{languageZH, languageEN})
db.Model(&user).Association("Languages").Replace(Language{Name: "DE"}, languageEN)删除关联
如果存在,则删除源模型与参数之间的关系,只会删除引用,不会从数据库中删除这些对象。db.Model(&user).Association("Languages").Delete([]Language{languageZH, languageEN})
db.Model(&user).Association("Languages").Delete(languageZH, languageEN)清空关联
删除源模型与关联之间的所有引用,但不会删除这些关联db.Model(&user).Association("Languages").Clear()
关联计数: 返回当前关联的计数
db.Model(&user).Association("Languages").Count()
// 条件计数
codes := []string{"zh-CN", "en-US", "ja-JP"}
db.Model(&user).Where("code IN ?", codes).Association("Languages").Count()批量处理数据
关联模式也支持批量处理,例如:// 查询所有用户的所有角色
db.Model(&users).Association("Role").Find(&roles)
// 从所有 team 中删除 user A
db.Model(&users).Association("Team").Delete(&userA)
// 获取去重的用户所属 team 数量
db.Model(&users).Association("Team").Count()
// 对于批量数据的 `Append`、`Replace`,参数的长度必须与数据的长度相同,否则会返回 error
var users = []User{user1, user2, user3}
// 例如:现在有三个 user,Append userA 到 user1 的 team,Append userB 到 user2 的 team,Append userA、userB 和 userC 到 user3 的 team
db.Model(&users).Association("Team").Append(&userA, &userB, &[]User{userA, userB, userC})
// 重置 user1 team 为 userA,重置 user2 的 team 为 userB,重置 user3 的 team 为 userA、 userB 和 userC
db.Model(&users).Association("Team").Replace(&userA, &userB, &[]User{userA, userB, userC})
带 Select 的删除
你可以在删除记录时通过 Select 来删除具有 has one、has many、many2many 关系的记录,例如:
// 删除 user 时,也删除 user 的 account
db.Select("Account").Delete(&user)
// 删除 user 时,也删除 user 的 Orders、CreditCards 记录
db.Select("Orders", "CreditCards").Delete(&user)
// 删除 user 时,也删除用户所有 has one/many、many2many 记录
db.Select(clause.Associations).Delete(&user)
// 删除 users 时,也删除每一个 user 的 account
db.Select("Account").Delete(&users)FullSaveAssociations
想要更新关联的数据,您应该使用 FullSaveAssociations 模式:db.Session(&gorm.Session{FullSaveAssociations: true}).Updates(&user)
预加载(preload, joins)
//链式加载 |
注意 Join Preload 适用于一对一的关系,例如:
has one
,belongs to